Design Patterns
- Principles
- The Strategy Pattern
- The Observer Pattern
- The Decorator Pattern
- The Factory Pattern
- The Singleton Pattern
- The Command Pattern
- The Adapter Pattern
- The Facade Pattern
- The Template Method Pattern
- The State Pattern
- The Proxy Pattern
- Model-View-Controller
- Design Pattern Categories
- References
Principles
-
Identify the varying parts and separate them from the invariant.
-
Program to an interface (supertype), not an implementation.
1 2 3
Animal animal = new Dog(); animal.makeSound(); List<Integer> list = new ArrayList<Integer>();
-
Favor composition over inheritance. HAS-A can be better than IS-A.
-
SOLID:
- Single responsibility: a class should have only one reason to change.
- Open-closed: classes should be open for extension, but closed for modification.
- Liskov Substitution: objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program
- Interface Segregation: many client-specific interfaces are better than one general-purpose interface.
- Dependency inversion: depend upon abstractions. Do not depend upon concrete classes. High-level components should not depend on low-level components; rather, they should both depend on abstractions.
- No variables should hold a reference to a concrete class.
- No class should derive from a concrete class.
-
Loose coupling: minimize the interdependency between objects.
-
Design by contract: preconditions, postconditions, and invariants.
-
Principle of Least Knowledge aka (Law of Demeter): talk only to your immediate friends.
-
The Hollywood Principle (aka. Inversion of Control): (High-level components) Don’t call us, we’ll call you (low-level components).
- A form of IoC: Dependency injection - a technique in which an object receives other objects that it depends on.
-
Tell-Don’t-Ask: A->B instead of B->A->B for data.
-
Build end-to-end (incrementally) instead of top-down nor bottom-up.
-
In a Test-driven development (TDD), there’s no need to do a big design up front.
-
There’s no need to prefix
m_
for private stuff. -
We shouldn’t always use patterns in today’s agile and XP trends. But if our specific solution is similar to a pattern, refactor it to make it more generic if needed.
The Strategy Pattern
- The strategy pattern enables selecting an algorithm at runtime. Instead of implementing a single algorithm directly, code receives run-time instructions as to which in a family of algorithms to use.
The Observer Pattern
-
Publishers (Subject) + Subscribers (Observers) = Observer Pattern.
-
It defines a one-to-many dependency. When the subject changes, all dependents are notified.
-
In Java, we can use the built-in Observable - Observer superclasses.
1 2 3 4 5 6
// extends Observable setChanged(); notifyObservers(); // extends Observer // in the constructor observable.addObserver(this);
-
In Java, Observable is a class, which means we have to subclass it.
-
UML:
- Example:
-
Used principles:
- Loose coupling.
The Decorator Pattern
-
Decorators have the same supertype as the object they decorate.
-
You can use one or more decorators to wrap (HAS-A) an object.
-
The decorator adds its own behavior either before and/or after delegating to the object it decorates to do the rest of the job.
-
The decorator pattern attaches additional responsibilities to an object dynamically.
-
UML:
- Example:
-
java.io
is mainly using the decorator pattern. -
Used principles:
- Open-closed.
The Factory Pattern
-
The factory method pattern defines an interface for creating an object, but lets subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
-
UML:
- Example:
-
The abstract factory pattern provides an interface for creating families of related or dependent objects without specifying their concrete classes.
-
Used principles:
- Dependency inversion.
The Singleton Pattern
-
The singleton pattern restricts the instantiation of a class to one single instance, and provides a global point of access to it:
1 2 3 4 5 6 7 8 9 10
public class Singleton { private static Singleton uniqueInstance; private Singleton() {} // PRIVATE constructor public static synchronized Singleton getInstance() { // remove synchronized if there's no multithreading if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; } }
The Command Pattern
-
The command pattern encapsulates a request as an object, thereby letting you parameterize other objects with different requests and support undoable operations.
-
UML:
The Adapter Pattern
-
The adapter pattern converts the interface of a class into another interface the clients expect. It lets classes work together that couldn’t otherwise because of incompatible interfaces.
-
UML:
The Facade Pattern
-
The facade pattern 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.
-
Used principles:
- Least knowledge.
The Template Method Pattern
-
The template method pattern defines the skeleton of an algorithm in a method, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
abstract class AbstractClass { final void templateMethod() { primitiveOperation1(); primitiveOperation2(); concreteOperation(); } abstract void primitiveOperation1(); abstract void primitiveOperation2(); void concreteOperation() { // implementation here } }
-
Used principles:
- Inversion of control.
- Single responsibility.
The State Pattern
-
The state pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class.
-
It’s close to the concept of finite-state machines.
The Proxy Pattern
-
A remote proxy acts as a local representative to a remote object.
-
Java RMI’s (remote method invocation) client helper is a “stub” and the service helper is a “skeleton”. The stub is the proxy.
-
The proxy pattern provides a surrogate or placeholder for another object to access it.
Model-View-Controller
- The MVC is using:
- the strategy pattern: the view delegates to the controllers to handle user actions. (Swappable controllers.)
- the composite pattern: the view is a composite of GUI components.
- the observer pattern: the model is the observable, and the view & controller are observers.
Design Pattern Categories
- Creational: Factory, Singleton
- Behavioral (how classes communicate): State, Iterator, Command
- Structural: Adapter, Composite, Decorator, Facade, Proxy