Overview

10 The Adapter and Façade Design Patterns

This chapter tackles the recurring challenge of working with external or legacy code that you can’t (or don’t want to) modify and presents two design patterns that make such code easier to use: Adapter and Façade. Adapter reconciles incompatible interfaces so existing components can collaborate without changes, while Façade hides the complexity of a subsystem behind a single, higher-level interface. Through Python examples drawn from sports reporting and athletic fund-raising, the chapter demonstrates how each pattern improves design by isolating change, reducing coupling, and simplifying client code.

For Adapter, the chapter begins with a brittle design in which a reporting class both converts data and prints it, tightly coupling it to the details of each source and making extensions costly. Introducing adapter classes (e.g., FootballData, VolleyballData) that implement a common GameData interface and wrap legacy sources decouples conversion from reporting and lets the legacy printing routine operate uniformly. The result encapsulates data transformation (Encapsulate What Varies), enforces single responsibility, and loosens coupling. The generic Adapter model (Target, Adapter, Adaptee) is presented along with an alternative “class adapter” using multiple inheritance; guidance is given on choosing between object adapters (composition, shareable, adapts subclasses) and class adapters (inheritance, can override Adaptee behavior).

For Façade, the chapter contrasts a duplicated, order-sensitive orchestration of multiple components (Alumni, BoosterClubs, Students) with a cleaner design that introduces a FundRaiser façade exposing a single do_fund_raising() method. Clients (AthleticsDept, Administration) no longer depend on the subsystem’s interfaces or call sequence; duplication is removed (DRY), coupling is reduced (Principle of Least Knowledge), and the subsystem becomes easier to extend (e.g., adding CorporateSponsors affects only the façade). The generic Façade model is outlined, and the chapter closes with guidance: use Adapter when you must fit disparate code to a required interface, and use Façade when you want a unified, simpler entry point that hides a complex subsystem.

In the first version of the application, classes BaseballData, FootballInfo, and VolleyballStats present their venue and attendance data in different ways. Therefore, class AttendanceReport has three overloaded public print() methods. But the class’s legacy method legacy_print(), which we cannot change, can only print GameData objects. Therefore, the class has a nested private class _ConvertedData to convert FootballInfo and VolleyballStats objects to GameData objects. BaseballData is already an GameData object.
This version of the application uses the Adapter Design Pattern. Adapter classes FootballData and VolleyballData each implements the GameData interface. Each wraps classes FootballInfo and VolleyballStats, respectively, and encapsulate the data conversion code. The grayed-out portions of the diagram have not changed logically from figure 10.1.
The generic model of the Adapter Design Pattern. Compare with figure 10.2. The Adapter class implements the Target interface. It adapts an Adaptee class by wrapping it so that the latter can work with the Target interface.
In the alternative version of the Adapter Design Pattern, adapter class FootballData implements the GameData interface and inherits from (rather than aggregates) the FootballInfo class. Adapter class VolleyballData implements the GameData interface and inherits from the VolleyballStats class. Neither adapter class does wrapping. The grayed-out portions of the diagram have not changed logically from figure 10.2.
The model of the alternative version of the Adapter Design Pattern. Compare with figure 10.4. The Adapter class relies on multiple inheritance.
To perform fund raising, classes AthleticsDept and Administration each must call the appropriate methods of classes Alumni, BoosterClubs, and Students.
The architecture modeled from the Façade Design Pattern hides the details of fundraising behind the façade class FundRaiser which presents a higher-level interface that simplifies using the subsystem consisting of classes Alumni, BoosterClubs, and Students.
The generic model of the Façade Design Pattern. Compare with figure 10.7. The Façade class hides the interfaces of the subsystem classes and makes the subsystem consisting of classes Alumni, BoosterClubs, and Students easier to use.

Summary

  • The Adapter Design Pattern models a software architecture that converts the interface of the adaptee class to a target interface. This allows integrating codes that weren’t originally designed to work together.
  • One version of the Adapter Design Pattern uses object composition to wrap an object of the adaptee class in an adapter class that implements the target interface.
  • The other version of the pattern relies on multiple inheritance, where the adapter class implements the target interface and is a subclass of the adaptee class.
  • The Façade Design Pattern hides the multiple interfaces of a subsystem of classes with a simpler and higher-level interface, thereby making the subsystem easier to use.

FAQ

What problem does the Adapter Design Pattern solve in this chapter?It integrates external or legacy code that has an incompatible interface with an existing application that you can’t (or don’t want to) modify. In the example, the legacy printer accepts only GameData objects, but FootballInfo and VolleyballStats expose their data differently, so adapters are introduced to make them look like GameData.
How is the attendance report refactored using Adapter?Two adapters, FootballData and VolleyballData, are created that implement the GameData interface. Each adapter wraps its corresponding external class (FootballInfo or VolleyballStats) and translates calls to report_venue() and report_attendance(). AttendanceReport keeps a single legacy_print(game_data, title) that accepts any GameData, removing conversion logic from the report class.
What were the main faults before applying Adapter?- AttendanceReport had multiple responsibilities (printing and converting data). - It was tightly coupled to FootballInfo and VolleyballStats internals. - It was inflexible: adding a new sport required changing AttendanceReport and adding another print overload. - It duplicated conversion logic via a private _ConvertedData class.
What is the difference between an object adapter and a class adapter?- Object adapter: uses composition (wrapping). The adapter holds a reference to the adaptee and forwards/translates calls. It can be shared, can wrap any adaptee subclass, and cleanly isolates changes. - Class adapter: uses multiple inheritance to inherit from the adaptee while implementing the target interface. The client doesn’t need to know about the adaptee, and the adapter can override adaptee behavior. Choose based on sharing needs, subclass coverage, and whether overriding via inheritance is desirable.
How do I add a new sport (e.g., basketball) after adopting Adapter?Create a BasketballData adapter that implements GameData and wraps the external basketball data source (e.g., BasketballInfo). Map its interface to report_venue() and report_attendance(), then pass the adapter to AttendanceReport. No changes to AttendanceReport are needed.
How does Adapter isolate the app from external interface changes?The application depends only on the stable target interface (GameData). Any changes in FootballInfo or VolleyballStats are handled inside their adapters. This satisfies the desired features of not modifying app or external code and isolating the app from external interface changes.
What problem does the Façade Design Pattern solve in this chapter?It hides a complex subsystem behind a simpler, unified interface, making it easier to use and reducing coupling. In the example, FundRaiser.do_fund_raising() encapsulates calls to Alumni, BoosterClubs, and Students so clients don’t need to coordinate those components or their call order.
How is the fundraising example refactored using Façade?A new façade class, FundRaiser, exposes do_fund_raising() and internally calls Alumni.send_solicitations(), BoosterClubs.schedule_meetings(), and Students.collect_fees(). AthleticsDept and Administration now call only the façade, removing duplicated code and direct dependencies on subsystem classes.
What desired design features are addressed by Adapter and Façade here?- Adapter: (DF1) no modifications to app or external code, (DF2) app isolated from external interface changes, (DF3) easy to add new sports. - Façade: (DF1) clients don’t depend on subsystem interfaces/implementations, (DF2) clients are not concerned with operation order, (DF3) clients interact with a single interface.
When should I choose Adapter vs. Façade (or both)?Use Adapter when you must make incompatible interfaces work together by converting to a target interface (e.g., adapting FootballInfo to GameData). Use Façade when you want to simplify usage of a complex subsystem by fronting it with a higher-level interface (e.g., FundRaiser). They are complementary and can be used together in the same system.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Software Design for Python Programmers ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Software Design for Python Programmers ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Software Design for Python Programmers ebook for free