Decorator Mode: Dynamically attaches responsibility to an object
The Java I/O API is also used in this mode
The class diagram for the decorating mode is as follows:
Abstract component (Component): An abstract class, or an interface, that regulates the object that receives responsibility dynamically.
Specific component (concrete Component): Defines a class that will receive additional responsibilities, which can be used alone or packaged by the adorner.
Abstract decorative Component (Decorator): An abstract class or an interface that has an instance of a component (Component) object and defines an interface that is consistent with an abstract component interface.
Specific decorative components (concrete componenta,concrete COMPONENTB): Responsible for decorating the specific components, to add responsibility for the specific components, the decorator has an instance variable, can be recorded by the decorator; the decorator can expand the state of component, You can also add new methods, and the new behavior is added by doing some calculations before or after the old behavior.
For example: Xiao Ming wants to open a drink shop, need to set the classification and price of drinks, the main raw material is water, the other raw materials we call seasoning, including milk, white sugar, coffee powder, black tea, fruit and so on, plus the seasoning is not the same, the price of the drinks are not the same, the price of various materials are as follows
Raw materials |
Price (RMB) |
Water |
1 |
Milk |
2 |
Coffee Powder |
2 |
Black tea |
1 |
Green tea |
1 |
Cranberry |
2 |
Lemon |
2 |
Sugar |
1 |
The specific class diagram is as follows:
The specific code is as follows:
1 //An abstract class, equivalent to an abstract component in a class diagram, where all the decorators inherit the class and implement the abstract method2 Abstract classdrink{3String Description = "Unknow Drink";4 //defines the method that gets the description, returns the variable description5 PublicString getdescription () {6 returndescription;7 }8 //abstract methods, all of which inherit the abstract class, need to implement the method9 Public Abstract intCost ();Ten } One //A concrete implementation class, equivalent to a specific component in a class diagram, is generally considered to be a decorator A classWaterextendsdrink{ - Publicwater () { -Description = "Water"; the } - @Override - Public intCost () { - return1; + } - } + A //Abstract Decorative Components at Abstract classCondimentextendsdrink{ - Drink Drink; - Publiccondiment (Drink Drink) { - This. Drink =drink; - } - Public AbstractString getdescription (); in } - /** to * Specific decorative components: need to allow the decorator to hold the decorated person, as follows: + * 1: Define a decorator's instance variable - * 2: Find a way to let the decorator record in the instance variable, the practice here is through the constructor function to implement the * @authorSAMSUNG * * $ */Panax Notoginseng classRedteaextendscondiment{ - PublicRedtea (Drink tmpdrink) { the Super(tmpdrink); + } A //Get the complete description, in addition to their own description, also through the delegate, get the description of the decorator, the combination of both to get a complete description the @Override + PublicString getdescription () { - returnDrink.getdescription () + "Add black tea"; $ } $ @Override - Public intCost () { - return2 +drink.cost (); the } - }Wuyi //Specific Decorative Components the classSugarextendscondiment{ - PublicSugar (Drink tmpdrink) { Wu Super(tmpdrink); - } About @Override $ PublicString getdescription () { - - returnDrink.getdescription () + "add white sugar"; - } A @Override + Public intCost () { the return1 +drink.cost (); - } $ } the the //Specific Decorative Components the classLemonextendscondiment{ the PublicLemon (Drink tmpdrink) { - Super(tmpdrink); in } the @Override the PublicString getdescription () { About the returnDrink.getdescription () + "Add lemon"; the } the @Override + Public intCost () { - return1 +drink.cost (); the }Bayi } the the - //Test Class - Public classDrinktest { the the Public Static voidMain (string[] args) { the theDrink Drink1 =Newwater (); - //Print the information of the decorator who does not add any decorators theSystem.out.println (drink1.getdescription () + "Price:" +drink1.cost ()); the //Decorate with Redtea theDRINK1 =NewRedtea (DRINK1);94System.out.println (drink1.getdescription () + "Price:" +drink1.cost ()); the //Decorate with sugar theDRINK1 =NewSugar (DRINK1); theSystem.out.println (drink1.getdescription () + "Price:" +drink1.cost ());98 //Decorate with lemon AboutDRINK1 =NewLemon (DRINK1); -System.out.println (drink1.getdescription () + "Price:" +drink1.cost ());101 }102}
The results of the operation are as follows:
Code Analysis:
1, the abstract class can be replaced by an interface, the interface is an extremely abstract type, more abstract than the abstract class;
2. Decorative abstract class (condiment) holds a reference to the abstract class (Drink) of the adorner, passing the constructor, passing in an object of the Drink as a parameter, and assigning the parameter to the reference so that the decorator can hold the adorner;
3, all the specific decorator's constructor calls the Super(Tmpdrink) method, the concrete implementation of dependency abstraction, embodies the principle of dependency inversion, when a new decorator joins, do not need to modify the code, just define a new assembly class, And let the class inherit the decorator abstract class, it can become a new concrete decorator, embodies the expansion of open, to modify the design principles of closure;
4, by the results of the operation can be seen: a plurality of decorators may package a decorator, called the decorator chain;
5, the Decorator (condiment) and the decorator (Water) have the same type , although the use of inheritance, the purpose of using inheritance is to achieve "type matching", rather than get "behavior", if you rely on inheritance, then the behavior of the class can only be statically determined at compile time, Conversely, by using a combination, the decorator can be used to add new behavior at run time.
The pros and cons of decorator mode:
Advantages:
1, can add a lot of extra behavior to the object, extend the behavior of the object, more flexible than inheritance;
2, through the different decoration class, or a plurality of decoration class arrangement combination, in the run time changes the object behavior, makes the object has the more powerful function;
Disadvantages:
1, will produce a lot of small objects, multi-use words increase the complexity of the system;
2, although more than the inheritance has a high flexibility, but also means that the likelihood of error is higher, troubleshooting is more troublesome.
Design Patterns Learning Notes: Three