The Decorator Pattern is a structural design pattern that allows you to dynamically add new behavior to an object without altering its structure or affecting other objects. This pattern works by wrapping the original object inside a “decorator” object, enabling behavior extension while keeping the original object’s type unchanged.
Object Composition: The Decorator Pattern relies on composition rather than inheritance. You wrap one object inside another to add additional functionality.
Same Interface: Both the decorator and the decorated object usually implement the same interface or inherit from the same parent class, making them interchangeable.
Dynamic Extension: New functionality can be added at runtime, unlike inheritance, where behavior is fixed at compile time.
Below is a simple example of the Decorator Pattern:
1 2 3 4 5
// Base interface for coffee interfaceCoffee { String getDescription(); doublegetCost(); }
1 2 3 4 5 6 7 8 9 10 11 12
// Concrete base coffee implementation (decorated object) classSimpleCoffeeimplementsCoffee { @Override public String getDescription() { return"Simple Coffee"; }
@Override publicdoublegetCost() { return5.0; // Base price } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
// Abstract decorator class abstractclassCoffeeDecoratorimplementsCoffee { protected Coffee decoratedCoffee;
The decorated object is the implementation class SimpleCoffee of the Coffee interface. The abstract decorator base class is CoffeeDecorator, and the two concrete decorators are MilkDecorator and SugarDecorator.
In this scenario, MilkDecorator and SugarDecorator decorate SimpleCoffee, extending its functionality without modifying its structure or inheritance hierarchy.
Adapter Pattern
The Adapter Pattern is a structural design pattern that converts the interface of a class into another interface that clients expect. It allows classes with incompatible interfaces to work together.
This pattern is particularly useful when you want to reuse existing classes, but their interfaces do not match your current requirements.
Interface Conversion: The core of the Adapter Pattern is converting one interface into another expected by the client.
Class Adapter vs Object Adapter:
Class Adapter: Uses inheritance to adapt functionality.
Object Adapter: Uses composition to adapt functionality. It is more flexible because it depends on interfaces rather than concrete implementations.
Example:
1 2 3 4
// Target interface - Power socket interfacePowerSocket { voidplugIn(); }
The Proxy Pattern can be summarized as: extending the functionality of an original interface through an intermediary object, without modifying the original interface.
Example:
1 2 3 4
// Original interface publicinterfaceBrowser { voidrequest(); }
Hello everyone,I'm 4pril. This website is solely for recording the learning process and the journey of coding. If there is any infringement, please feel free to contact me. Meanwhile, I welcome everyone to share and exchange experiences with me. Have fun ;)