Composite allows us to treat both single objects and composite objects uniformly via inheritance (through method calls). To use composite:
- Create interface/parent class
- Create new single element class that implements the interface
- Create composite element class that implements the interface
The composite class has:
- A List<> containing the single elements
- A method for adding elements to it
- Same methods as the single elements (from implementing interface)
- Methods that delegate calls to its single elements
See Composite.java
Decorator allows adding additional functionality to class without modifying or subclassing it. To use decorator:
- Create interface
- Create class that implements interface
- Create decorator class that implements interface and has the class created in step 2 as field
Characteristic of decorator class:
- Decorated class as a field (often received from constructor)
- Same methods as the decorated elements (from implementing interface)
- Method makes calls to decorated elements
See Decorator.java
Prototype is a template object that can be used as a shortcut to create new objects with similar attributes. You can either implement Cloneable (not recommended) or create your own copy() method
- Shallow copy (immutable fields): simply return
super.clone()
in a try-catch block - Deep copy (mutable fields): create a new object and copy each field manually. If class has a lot of immutable fields, get clone from
super.clone()
and copy each mutable field manually
See Prototype.java
Command design pattern allows encapsulation of requests or operations as objects. It seperates the object that invokes the operation from the receiver of the action. It allows support for undo and redo, and simplifies code by isolating specific functionality into separate classes
- Before: Invoke command
$\rightarrow$ Perform action - After: Invoker creates command object
$\rightarrow$ Execute command object$\rightarrow$ Perform action
To use the Command design pattern:
- Create a receiver class that actually performs actions. Each action should be a different method.
- Create a command interface that declares method for executing and potentially undo a command
- Create a concrete command object that implements the interface. This class is the request encapsulated as an object. It should execute a specific method in the receiver class.
- Create instances of the concrete command object and execute it
See Command.java
Law of Demeter promotes encapsulation and makes code more modular and easier to maintain. The main takeaway is to reduce dependency.
A method is allowed to access the following:
- Arguments passed to the method
- Fields and methods declared in the same class
- Global objects
- Anything created within the method