Table of contents generated with markdown-toc
-
- Defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
- Enable the extensible creation of variabilities such as commands, iterators, and visitors.
-
- Decouples the implementation of the product from its use.
- Clients are more flexible since they don't need to specify the class name of the concrete class and the details of its creation.
- Adding new variants does not affect existing client code.
-
- When the class cannot anticipate the objects it must create.
- When the class wants its subclasses to specify the objects it creates.
- When there's a need to decouple object creation from its subsequent use.
- When you need to construct multiple instances of the object or if the object needs to be constructed lazily (e.g. the object is expensive to construct, you don't use it in all code paths, and you want to defer construction to the code paths that actually use it).
- Construction of objects may require additional classes.
-
- When the calling code can create the object upfront and simply supply it (e.g. there is only one instance used and it doesn't need to be created lazily), then you should simply take the object (not its factory) as a parameter. Avoids an unnecessary level of indirection.
- Very simple objects that are inexpensive and simple to create (do not need to be lazily created, don't have many constructor parameters) and have only one type (or very few, limited, well-known subtypes) should generally be constructed directly rather than with a factory. For example, creating primitives or other simple objects (2d points, complex numbers, etc.) with a factory is a "code smell".
-
- Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
- Methods are often implemented as factory methods. Each method is responsible for creating a concrete product. The subclass of the abstract factory supplies those implementations.
-
- Decouople code from the actual factories that produce products meant for different contexts-such as different regions, operating systems, or looks and feels.
- Provides a powerful technique for coding to abstractins, not contrete classes.
-
- When you have families of products you need to create and you want to make sure your clients create products that belong together.
-
- Encapsulate the construction of a product and allow it to be constructed in steps. Separates construction of a complex object from its representation.
-
- Isolates the code from construction and representation.
- Fine control over construction process. Allows objects to be constructed in a multistep and varying process (as opposed to one-step factories).
- Hides internal representation of the product from the client.
- Product implementations can be swapped in and out because the client only sees an abstract interface.
-
- When you need to follow a sequence of potentially complex steps to create an object.
- Allow different implementations and internal interfaces of an object.
- Goes nicely with interpreter pattern (compound).
- May involve a lot of classes and class interdependencies.
- Constructing objects requires more domain knowledge of the client than when using a Factory.
-
- Ensures a class has only one instance, and provides a global point of access to it.
- Different ways of implementing for thread safety (eager loading, double-checked locking)
- Examine your performance and resource constraints and carefully choose an appropriate Singleton implementation for multithreaded applications.
-
- Provides a global access point to the instance.
-
- When you need one and only one instance of an object such as thread pools, connections, caches, dialog boxes, objects that handle preferences and registry settings, objects used for logging, and objects that act as device drivers to devices like printers and graphics cards.
- When you want to create a single instance lazily.
- May not be thread-safe depending on the implementation.
-
- Attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
- Involves a set of decorator classes that are used to wrap concrete components.
- Decorators mirror the type of the components they decorate, either through inheritance or interface implementation.- Can insert decorators transparently and the client never has to know it's dealing with a decorator.
- Decorators are typically transparent to the client of the component, unless the client is relying on the component's concrete type.
-
- Allows classes to be easily extended to incorporate new behavior without modifying existing code.
- Objects can be decorated at any time, so we can decorate objects dynamically at runtime with as many decorators as we like.
-
- When you need to change the behavior of components by adding new functionality before and/or after (or even in place of) delegating to the object it decorates.
- Adds a lot of small classes to a design and this occasionally results in a design that's less than straightforward for others to understand.
- Some code is dependent on specific types which can break when introducting a decorator.
-
- Build structures of objects in the form of trees to represent part-whole hierarchies that contain both compositions of objects and individual objects as nodes. Using a composite structure, we can apply the same operations over both composites and individual objects, ignoring the differences between composites and individual objects.
-
- Treat individual objects and multiple, recursively-composed objects uniformly regardless of complexity and behavior.
- No distinction between individual and composed elements.
- New component subclasses work wherever existing ones do.
- Classes only include fields and methods they need.
-
- Let clients treat individual objects and compositions as objects uniformly.
- Perceived complexity. May need what seems a large number of classes and objects.
- Bloated interfaces for composites and leaves. Leaf inherits methods it doesn't need.
-
- Decouple an abstraction from its implementation so that the two can vary independently. This means to create a bridge interface to separate out responsibilities into different abstract classes.
- Encapsulate variability behind a stable API that creates separate class hierarchies for an abstraction and its implementations. Client calls to the abstraction are forwarded to the corresponding implementor subclass.
- The Bridge pattern is an application of the old advice, “prefer composition over inheritance”.
-
- Decouples an implementation so that it is not bound permanently to an interface.
- Abstraction and implementation can be extended independently.
- Changes to concrete abstraction classes don't affect the client.
-
- Useful any time you need to vary an interface and an implementation in different ways.
- Useful in graphics and windowing systems that need to run over multiple platforms.
- When there's a need to change implementor hierarchies at design-time or runtime without breaking client code.
- Increases complexity.
-
- Converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
- The job of implementing an adapter is proportional to the size of the interface you need to support as your target interface.
- Class adapters are different than object adapters. Class adapters subclass the target and adaptee, while with object adapter we use composition to pass requests to an Adaptee. Class adapters require multiple inheritance.
- Converts one interface to another one a client expects.
- An adapter wraps an object to change its interface.
-
- Decouples the client from the implemented interface. If we expect the interface to change over time, the adapter encapsulates that change so the client doesn't have to be modified each time it needs to operate against a different interface.
- Binds the client to an interface, not an implementation.
- Clients can make use of new libraries and subsets without changing any code.
-
- When you need to adapt an interface to one that the client is expecting.
- When you need to use an existing class and its interface is not the one you need.
-
- Provides a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.
- Avoids tight coupling between clients and subsystems.
- Subsystem classes still remain available for direct use by clients that need to use more specific interfaces.
- Provides a simplified interface while still exposing the full functionality of the system to those who may need it.
- Uses delegation to perform the work of the facade.
-
- Takes a complex subsystem and makes it easier to use.
- Allos updating a subsystem without having to change the client code.
-
- When you want to hide all the complexity of one or more classes behind a clean, well-lit facade.
- When you want to decouple your client implementation from any one subsystem.
- High degree of dependence at facade interface.
- Complex implementation (especially with existing code).
-
- Provides a surrogate or placeholder for another object to control access to it.
- Similar in structure to Facade, Decorator, and Adapter but different in purpose.
- Proxies wrap another object to control access acting as a surrogate of a real subject
- Decorators wrap another object and provide a different interface to it.
- Facades wrap another object and provide additional behavior to it.
- Adapters wrap a bunch of objects to simplify their interface.
-
- Security.
- Avoids duplication of objects which might be huge in size and memory intensive, increasing performance of the application.
- Remote proxy ensures security by installing the local code proxy (stub) in the client machine and then accessing the server with help of remote code.
-
- When you need to create a representative object that controls access to another object, which may be remote, expensive to create, or in need of securing.
- When you need to create a wrapper to cover the main object's complexity from the client.
- Introduces another layer of abstraction which may be an issue if the real subject code is accessed directly by some clients and some of them might access the proxy classes. This might cause disparate behavior.
-
- Virtual proxy: acts as a representative for an object that may be expensive to create. Defers the creation of the object until it is needed; the Virtual Proxy also acts as a surrogate for the object before and while it is being created. After that, the proxy delegates requests directly to the RealSubject.
-
- Popularity: low
- Uses sharing to support large number of fine-grained objects efficiently. It 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.
-
- Reduces the number of object instances at runtime, saving memory.
- Centralizes state for many "virtual" objects into a single location.
-
- When an application needs to spawn a huge number of similar objects.
- When the objects contain duplicate states which can be extracted and shared between multiple objects.
- Once you've implemented it, single, logical instances of the class will not be able to behave independently from the other instance.
-
- Defines a family of algorithms, encapsulates each one, and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.
- Change behaviors transparently. Encapsulate variability of behaviors via a common API whose implementations can be changed transparently with respect to clients.
-
- Decouples the interface of a behavior from its implementation. It creates an abstraction that makes it easy to select and exchange behaviors.
- Greater flexibility and reuse.
- Behaviors can change dynamically.
-
- When an object should be configurable at runtime with one of many algorithms and all algorithms can be encapsulated and one interface covers all encapsulations.
- Use as an alternative to subclassing.
- Overhead of strategy creation and communication. Strategy can increase the number of objects created in a program.
- Semantic incompatibility of multiple strategies used together inconsistently. May require other patterns such as abstract factory so groups of strategies that require semantic coherence evolve in a consistent way (concurrent or distributed systems).
-
- Defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.
- Observables (subjects) update observers using a common interface.
- You can push or pull data from the Observable when using the pattern (pull is considered more "correct").
-
- Observers are loosely coupled in that the Observable knows nothing about them, other than that they implement the observer interface.
- It allows sending data to other objects effectively without any change in the Subject or Observer classes.
- Observers can be added/removed at any point in time.
-
- When you need to notify a change of state and push data to several observers.
- When you need to "listen in" on any types of actions that might occur on a control, like a button press.
- Social media, RSS feeds, email subscription in which you have the option to follow or subscribe and you receive latest notification.
- The Observer interface has to be implemented by ConcreteObserver, which involves inheritance. There is no option for composition.
-
- Encapsulate the request for a service as an object, thereby letting you parameterize other objects with different requests, queue or logs requests, and support undoable operations.
- Define objectified actions that enables users to perform command requests consistently and extensibly.
- Provides a common API for user-request commands.
-
- Decouples an object making a request from the one that knows how to perform it.
- Abstracts the executor of a service making the program more modular and flexible.
- Can bundle state and behavior in one object or forward behavior to other objects.
- Can extend behavior via subclassing.
- Can pass a command object as a parameter.
- Composition yields macro commands. Macro commands are a simple extension of Command that allow multiple commands to be invoked.
- Supports arbitrary level undo-redo.
-
- Implement logging, undo(), and transactional systems.
- Drawing editors, Microsoft Office tools, GNU Emacs.
- Might result in lots of trivial command subclasses.
- Excessive memory may be needed to support undo/redo operations.
- Avoiding error accumulation during undo/redo in numerical analysis applications.
-
- Provides a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
- It also places the task of traversal on the iterator object, not on the aggregate, which simplifies the aggregate interface and implementation, and places the responsibility where it should be.
-
- Flexibility. Aggregate and traversal objects are decoupled and can evolve separately.
- Multiplicity. Supports multiple iterators and traversal algorithms.
-
- When you require multiple traversal algorithms over an aggregate.
- When you require a uniform traversal interface over different aggregates.
- When aggregate classes and traversal algorithms must vary independently.
- Overhead. Additional communication between iterator and aggregate. Problematic for iterators in concurrent or distributed systems.
- Dependencies. The iterator implementation may depend on aggregate's implementation.
-
- It allows an object to alter its behavior when its internal state changes. The object will appear to change its class without changing its API.
- Represents a state as a full-blown class. The context gets its behavior by delegating to the current state object it is composed with.
- Allows a Context to change its behavior as the state of the Context changes. This is different from Strategy which typically configures Context classes with a behavior or algorithm. Strategy doesn't have clients accessing the methods through context which is used to store data from the "one size fits all" interface the strategy exposes.
-
- By encapsulating each state into a class, we localize any changes that will need to be made and partition behavior for different states.
- State transitions can be controlled by the State classes or by the Context classes.
-
- When an object must change its behavior at runtime depending on which state it is in.
- When several operations have the same large multi-part conditional structure that depends on the object's state.
- Will typically result in a greater number of classes in your design.
- Dependencies and interactions may be hard to understand and evolve if they aren't well documented (& if the State pattern isn't well understood)
-
- Defines the skeleton of an algorithm in a method, deferring some steps to subclasses. The Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
- Subclasses can "hook into" the algorithm at various points, if they wish through a hook method; a subclass is also free to ignore the hook. Hook methods do nothing or default behavior in the abstract class, but may be overriden in the subclass.
- The Hollywood Principle guides us to put decision making in high-level modules that can decide how and when to call low-level modules.
- Similar to strategy as both encapsulate algorithms, one by inheritance and the other by composition.
- The factory method is a specialization of Template method.
-
- Enables inversion of control (Hollywood Principle).
- Overriding rules are enforced via subclassing.
- Promotes code reuse.
-
- When you need to implement invariant aspects of an algorithm once and let subclasses define variant parts.
- When you want to localize common behavior in a class to enhance reuse.
- When you want to handle variations by subclassing.
- Must subclass to specialize behavior, which can yield many subclasses. Solves same problems as strategy pattern but in a different way.
-
- Popularity: low
- Without violating encapsulation, captures and externalizes an object's internal state so that the object can be restored to this state later.
- Its first goal is to save the important state of a system's key object.
- Its second goal is to maintain the key object's encapsulation.
- Keep the state separate from the key, or originator object. This seperate object is known as the Memento object.
-
- Keeping the saved state external from the key object helps to maintain cohesion.
- Keeps the key object's data encapsulated.
- Provides easy-to-implement recovery capability.
-
- When you need to be able to return an object to one of its previous states; for instance, if your user requests an "undo".
- When you need to save state.
- Saving and restoring state can be time consuming.
- Consider using serialization to save a system's state.