The decorator and the decorated have a common superclass. The purpose of inheritance is to inherit the type, not the behavior.
Decoration mode is to dynamically extend the function of an object without changing the original file and using inheritance. It wraps real objects by creating a wrapping object, that is, decoration. In fact, Java's I/O API is implemented using Decorator.
Characteristics of Decoration Mode
(1) Decorative objects and real objects have the same interface. In this way, client objects can interact with decorated objects in the same way as real objects.
(2) Decorative object contains a reference to a real object.
(3) Decorative objects accept all requests from clients. It forwards these requests to the real object.
(4) Decorative objects can add additional functions before or after forwarding these requests. This ensures that additional functions can be added externally without modifying the structure of a given object at runtime. In object-oriented design, the function extension of a given class is usually achieved through inheritance.
Applicability
Decorator mode is used in the following cases
1. You need to extend the functionality of a class or add additional responsibilities to a class.
2. It is necessary to add functions to an object dynamically, which can be revoked dynamically.
3. It is necessary to add a large number of functions generated by the arrangement and combination of some basic functions, so as to make the inheritance relationship unrealistic.
4. When the method of generating subclasses can not be used to expand. In one case, there may be a large number of independent extensions that will generate a large number of subclasses to support each combination, making the number of subclasses explosive. Another scenario may be that class definitions are hidden, or that class definitions cannot be used to generate subclasses.
Advantage
1. Decorator patterns and inheritance relationships are designed to extend the functionality of objects, but Decorator can provide more flexibility than inheritance.
2. Designers can create many combinations of different behaviors by using different specific decorative categories and the arrangement and combination of these decorative categories.
shortcoming
1. This feature is more flexible and flexible than inheritance, but also means more complexity.
2. Decoration patterns can lead to many small classes in the design. If overused, the program will become very complex.
3. Decoration pattern is programming for the type of abstract component. However, if you want to program for specific components, you should rethink your application architecture and the appropriateness of the decorator. Of course, it can also change the Component interface, add new public behavior, and realize the "translucent" decorator mode. In the actual project to make the best choice.
Design principles
1. Use more combinations and less inheritance.
The behavior of designing subclasses by inheritance is determined statically at compile time, and all subclasses inherit the same behavior. However, if the behavior of an object can be extended by using a combination approach, it can be extended dynamically at runtime.
2. Classes should be designed to be open to extensions and closed to modifications.
Mode simplification
1. Decorator can inherit Concrete Component if there is only one Concrete Component class and no abstract Component interface.
2. If there is only one Concrete Decorator class, you can merge Decorator and Concrete Decorator.
Code example
Here is an example of a software project to illustrate the use of decoration patterns
The process is as follows:
The project manager receives a project that eventually completes the coding.
After the project manager receives the project, he first does some preliminary work (such as requirement analysis, design), and then delegates the coding work to the coder. After the coder has finished, the project manager does the closing work of the project.
/** * Created by IntelliJ IDEA. * project */ public interface Project { /** * Writing code */ void doCoding(); }
/** * Created by IntelliJ IDEA. * Code worker */ public class Employe implements Project{ /** * Code */ public void doCoding(){ System.out.println("Code workers are writing code, overtime editing ah, finally finished!"); } }
/** * Created by IntelliJ IDEA. * project manager */ public class Manager implements Project { private Project project; //What's actually stored is code worker objects. public Manager(Project project) { this.project = project; } /** * Code */ public void doCoding() { //Project Manager Begins New Work startNewWork(); } /** * Template: Define the project manager's own business */ public void startNewWork() { //Project managers are doing early work doEarlyWork(); //The project manager is very good. After completing the requirements and design, he delegates the code directly to the coder. project.doCoding(); //The project manager is finishing up doEndWork(); } /** * Project Manager's Own Business: Do Early Work */ public void doEarlyWork() { } /** * Project Manager Finishing */ public void doEndWork() { } }
/** * Created by IntelliJ IDEA. * Specific Project Manager A */ public class ManagerA extends Manager{ public ManagerA(Project project) { super(project); } /** * Project Manager's Own Business: Do Early Work */ public void doEarlyWork() { System.out.println("project manager A Demand Analysis"); System.out.println("project manager A Architectural design in progress"); System.out.println("project manager A Detailed design in progress"); } }
/** * Created by IntelliJ IDEA. * Specific Project Manager B */ public class ManagerB extends Manager { public ManagerB(Project project) { super(project); } /** * Project Manager's Own Business: Do Early Work */ public void doEarlyWork() { System.out.println("project manager B Demand Analysis"); System.out.println("project manager B Detailed design in progress"); } /** * Project Manager Finishing */ public void doEndWork() { System.out.println("project manager B Finishing"); } }
/** * Created by IntelliJ IDEA. * Client Testing */ public class Client { public static void main(String args[]) { Project employe = new Employe(); //Code worker Project managerA = new ManagerA(employe); //project manager Project managerB = new ManagerB(employe); //project manager //Complete the coding in the name of the manager. All the credit is from the manager. The actual coding is from the worker. managerA.doCoding(); managerB.doCoding(); } }
Operation results: Project Manager A is doing requirement analysis Project Manager A is doing architecture design Project Manager A is doing detailed design Code workers are writing code, overtime editing ah, finally finished! Project Manager B is doing requirement analysis Project Manager B is doing detailed design Code workers are writing code, overtime editing ah, finally finished! Project Manager B is finishing up