They explain how to assemble objects and classes into larger structures, while keeping these structures flexible and efficient.
Allows objects with incompatible interfaces to collaborate.
Imagine that you’re creating a stock market monitoring app. The app downloads the stock data in XML format and then displays charts for the user. Then you decide to improve the app by integrating a smart 3rd-party analytics library. But there’s a catch: the analytics library only works with data in JSON format. You could change the library to work with XML. However, this might break some existing code that relies on the library. And worse, you might not have access to the library’s source code in the first place, making this approach impossible.
You can create an adapter. It wraps one of the objects to hide the complexity of conversion happening behind the scenes. The wrapped object isn’t even aware of the adapter.
Adapters can not only convert data into various formats but can also help objects with different interfaces collaborate. Sometimes it’s even possible to create a two-way adapter that can convert the calls in both directions.

The client contains existing logic and should remain unchanged. It depends only on a client interface, which defines a stable contract. The service provides the needed functionality but exposes an incompatible interface, so it cannot be used directly. The adapter implements the client interface, wraps the service, and translates calls and data between the two. As a result, the client stays decoupled from concrete services, and new or changed services can be integrated without modifying client code.

The Class Adapter doesn’t need to wrap any objects because it inherits behaviors from both the client and the service. The adaptation happens within the overridden methods. The resulting adapter can be used in place of an existing client class.
The overall complexity of the code increases because you need to introduce a set of new interfaces and classes. Sometimes it’s simpler just to change the service class so that it matches the rest of your code
Defines a high-level, unified, simplified interface to make a subsystem (library, a framework, or any other complex set of classes) easier to use.
Imagine that you have to make your code work with a broad set of objects that belong to a sophisticated library or framework. Ordinarily, you’d need to initialize all of those objects, keep track of dependencies, execute methods in the correct order, etc. As a result, the business logic of your classes would become tightly coupled to the implementation details of 3rd-party classes, making it hard to comprehend and maintain.
A facade is a class that provides a simple interface to a complex subsystem which contains lots of moving parts.
It might provide limited functionality in comparison to working with the subsystem directly; however, it includes only those features that clients really care about. It’s handy when a sophisticated library has dozens of features, but you just need a tiny bit of them.

It’s useless if the subsystem is already simple, it would add an unnecessary layer. There’s also the risk of a facade becoming a “god object”, a large object coupled to all classes of an app
AKA wrapper, it lets you attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors. Because the wrapper and the wrapped object share the same interface, client code can treat them interchangeably.
A common design problem has a simple base class (e.g. Notifier) that does one job well (e.g. sending e-mail notifications), then accumulates feature requests for optional variations (e.g. support for SMS, Facebook, Slack, etc. and a combination of them). Building a subclass for every combination causes a combinatorial explosion of classes.
Inheritance also has two core limitations here:
Instead of extending behavior through inheritance, Decorator uses composition. A decorator object keeps a reference to another object that follows the same interface and delegates work to it, while adding behavior before or after the delegated call.
Because each decorator implements the same interface as the wrapped object, you can stack multiple decorators on top of one another. This lets you combine behaviors dynamically at runtime.
In short: use Decorator when you want to add optional, composable behavior to objects dynamically without creating a large inheritance tree.

The pattern typically has these roles:
Component Declares the common interface shared by both core objects and decorators.
Concrete Component The original object being wrapped. It contains the base behavior.
Base Decorator
Stores a reference to a Component and delegates operations to it.
Concrete Decorators Add specific responsibilities before or after delegating to the wrapped object.
Client Works against the shared interface and can compose stacks of decorators as needed.
Lets you compose objects into tree structures and then work with these structures as if they were individual objects.
Some object models are naturally tree-shaped. For example, an order can contain products, but it can also contain boxes, and each box can contain more products or other boxes.
If client code has to calculate the total price, render the tree, or validate the structure, it may need to distinguish between simple objects and containers everywhere. This couples the client to many concrete classes and makes recursive logic spread through the codebase.
Composite defines a common interface for both simple elements and containers. A leaf object performs the actual work. A container object delegates the work to its children, combines their results, and exposes the same interface as a leaf.
Because both leaves and containers share the same contract, client code can treat the whole tree as one object. It does not need to know whether it is working with a single product or a box full of nested boxes.
The pattern typically has these roles:
Component Declares operations common to both simple and complex elements.
Leaf Represents an end object with no children and performs the real work.
Composite Stores child components and delegates work to them.
Client Works with all elements through the component interface.
Lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something either before or after the request gets through to the original object.
Sometimes an object is expensive, remote, sensitive, or needs extra behavior around access. For example, loading a large image, calling a remote service, checking permissions, caching results, or logging calls may all be useful, but adding that logic directly to the original class can mix responsibilities.
Changing client code everywhere is not ideal either. Clients should still depend on the same interface and should not need to know whether they are talking to the real object or a helper around it.
A proxy implements the same interface as the original service and keeps a reference to it. The proxy receives client requests, performs extra work if needed, and then forwards the request to the real object.
This lets you add lazy initialization, access control, caching, logging, remote communication, or other access-related behavior without changing the client and without bloating the service itself.
The pattern typically has these roles:
Service Interface Declares the operations used by the client.
Service Contains the real business logic.
Proxy Implements the same interface, controls access to the service, and delegates to it when appropriate.
Client Works through the service interface and can use either the real service or the proxy.
Lets you split a large class or a set of closely related classes into two separate hierarchies, abstraction and implementation, which can be developed independently.
Inheritance can explode when a class varies along multiple dimensions. For example, if you have shapes and colors, you may create RedCircle, BlueCircle, RedSquare, BlueSquare, and so on. Adding a new shape or color multiplies the number of subclasses.
This couples independent concepts together. A change in one dimension forces changes across many classes, even though shapes and colors could evolve separately.
Bridge replaces one large inheritance hierarchy with two linked hierarchies. The abstraction represents the high-level control layer, while the implementation represents the platform, variant, or low-level detail that actually performs the work.
The abstraction stores a reference to an implementation object and delegates work to it. This lets you combine abstractions and implementations at runtime and extend each side independently.
In short: use Bridge when two dimensions of variation should not be locked into one inheritance tree.
The pattern typically has these roles:
Abstraction Defines the high-level interface and keeps a reference to an implementation.
Refined Abstraction Extends the abstraction with extra behavior while still delegating implementation details.
Implementation Declares the low-level interface used by abstractions.
Concrete Implementations Provide platform-specific or variant-specific behavior.
Client Works with the abstraction and can choose which implementation to attach.
Lets you fit more objects into the available amount of RAM by sharing common parts of state between multiple objects instead of keeping all of the data in each object.
An application may need to create a huge number of similar objects. For example, a game may create thousands of particles, bullets, trees, or characters. If each object stores all of its data, memory usage can become too high.
Often, much of that data is repeated. Many trees may share the same texture, color, and species, while only their coordinates are different.
Flyweight splits object state into two parts:
Instead of creating many full objects, the app reuses a smaller set of flyweight objects that contain the shared state. A factory is often used to cache and return existing flyweights, so duplicates are not created.
The pattern typically has these roles:
Flyweight Stores shared intrinsic state and exposes behavior that accepts extrinsic state.
Concrete Flyweight Implements shared behavior and must not depend on unique per-object context stored inside itself.
Flyweight Factory Creates and caches flyweights, returning existing ones when possible.
Context Stores extrinsic state that is unique for each logical object.
Client Gets flyweights from the factory and passes external state when using them.