Decorator mode: Dynamically extends the functionality of an object without changing the original class file and using inheritance. It is by creating a wrapper object, that is, decorating to wrap the real object.
The role in decorator mode
Abstract component: is an interface or abstract class, that is, the definition of the most core object, is also the most primitive object, this class is required to decorate the class base class.
Specific components: is an implementation of the decorator's class, to decorate is the specific implementation class.
Abstract Decorator: Generally an abstract class, implements an interface or abstract method, which has a reference to the decorator, and it also inherits the abstract by the decorator.
Concrete Decorator: The specific decorator class.
Class diagram
Application Scenarios
Suppose there is a dessert shop where the price of dessert is based on the price of the raw material. For example: blueberry-flavored bread is the price of the base price of the bread plus the ingredients blueberry, and the blueberry-strawberry blend is made from the basic price of the cake plus the price of the toppings blueberry and strawberry.
Code implementation
Abstract components:
PackageCom.huey.pattern.decorator;/*** Dessert class, abstract by decorator*/ Public Abstract classDessert {protectedString Description = "Unknown Dessert"; /*** A description of the dessert, the method that needs to be decorated *@return */ PublicString getdescription () {returndescription; } Publicdessert () {}/*** The price of dessert, the way to be decorated *@return */ Public Abstract DoubleCost (); Public voiddisplay () {System.out.println ( This. GetDescription () + "¥" + This. Cost ()); }}
Specific component A:
Package Com.huey.pattern.decorator; /** */Publicclassextends dessert {public Bread () { = "Bread"; } @Override publicdouble Cost () { return 5.0; }}
Specific component B:
Package Com.huey.pattern.decorator; /** */Publicclassextends dessert {public Cake () { = "Cake"; } @Override publicdouble Cost () { return 9.90; }}
Abstract Decorator:
PackageCom.huey.pattern.decorator;/*** Seasoning class, Decorator's abstraction*/ Public Abstract classCondimentdecoratorextendsDessert {/*** Cited by the decorator*/ protecteddessert Dessert; Publiccondimentdecorator (dessert dessert) { This. Dessert =Dessert; } Public AbstractString getdescription (); Public Abstract DoubleCost (); }
Concrete Decorator A:
PackageCom.huey.pattern.decorator;/*** Blueberry class, Decorator's specific implementation*/ Public classBlueberryextendsCondimentdecorator { PublicBlueberry (dessert dessert) {Super(dessert); } /*** Extend the functionality of the method by the decorator's reference*/@Override Public DoubleCost () {returnDessert.cost () + 1.5; } /*** Extend the functionality of the method by the decorator's reference*/@Override PublicString getdescription () {returnDessert.getdescription () + ", Blueberry"; }}
Concrete Decorator B:
PackageCom.huey.pattern.decorator;/*** The specific realization of the chocolate class, the decorator*/ Public classChocolateextendsCondimentdecorator { PublicChocolate (dessert dessert) {Super(dessert); } /*** Extend the functionality of the method by the decorator's reference*/@Override Public DoubleCost () {returnDessert.cost () + 1.0; } /*** Extend the functionality of the method by the decorator's reference*/@Override PublicString getdescription () {returnDessert.getdescription () + ", chocolate"; }}
Unit tests:
PackageCom.huey.pattern.decorator; Public classDecoratorpatterntest { Public Static voidMain (string[] args) {/*** Non-decorated cakes*/Dessert Cake=NewCake (); Cake.display (); /*** cake decorated with chocolate*/Dessert Chocolatecake=NewCake (); Chocolatecake=Newchocolate (chocolatecake); Chocolatecake.display (); /*** decorated with chocolate and blueberry bread * can be decorated by a number of decorative people*/Dessert Blueberrychocolatebread=NewBread (); Blueberrychocolatebread=Newchocolate (blueberrychocolatebread); Blueberrychocolatebread=NewBlueberry (Blueberrychocolatebread); Blueberrychocolatebread.display (); }}
Result output:
Cake ¥9.9cake, chocolate ¥10.9bread, chocolate, Blueberry ¥7.5
Where decorator mode is applicable
1) When you need to dynamically add a new function or responsibility for an existing object, you can consider using decorator mode;
2) When the responsibilities of an object often change, or you often need to dynamically add responsibilities, avoid increasing the way you inherit subclass extensions in order to accommodate such changes.
Adorner mode in the Java SDK
In the JDK, the java.io part uses a lot of decorator patterns. Java.io.InputStream is the decorator pattern class diagram. In addition to Java.io.OutputStream, Java.io.Reader, Java.io.Writer and so on have also used a lot of decorator mode.
Design mode-Decorator mode