Add some additional responsibilities to an object dynamically. In terms of increased functionality, the decorator mode is more flexible than generating subclasses.
--"Design pattern" GoF
Role: Add responsibilities to a single object in a dynamic, transparent manner without affecting other objects.
For example, we now want to design a log class that logs a DB log (or text log)that requires the ability to record the priority and error levels of the log.
This adds the ability to record error levels and priorities for this log class. Additional functionality may also be added later.
Public Interface Log { publicvoid write (String logcontent);}
Public class Implements log{ @Override publicvoid write (String logcontent) { System.out.println ("record db-log:" + logcontent); } }
Public class Implements log{ @Override publicvoid write (String logcontent) { System.out.println ("record textfile-log:" + logcontent); } }
Logwrapper class to add new functionality to the log class:
Public Abstract class Implements log{ protected log log; @Override publicvoid write (String logcontent) { log.write (logcontent); } }
Public classLogerrorwrapperextendslogwrapper{PrivateString ErrorLevel; Publiclogerrorwrapper (log log) {Super(); This. log =log; } PublicString Geterrorlevel () {returnErrorLevel; } Public voidseterrorlevel (String errorLevel) { This. ErrorLevel =ErrorLevel; } @Override Public voidWrite (String logcontent) {logerrorlevel (errorLevel); Super. Write (logcontent); } Private voidlogerrorlevel (String errorLevel) {System.out.println ("Error Level:" +errorLevel); } }
Public classLogprioritywrapperextendslogwrapper{PrivateString priority; Publiclogprioritywrapper (log log) {Super(); This. log =log; } PublicString getpriority () {returnPriority ; } Public voidsetpriority (String priority) { This. Priority =Priority ; } @Override Public voidWrite (String logcontent) {logpriority (priority); Super. Write (logcontent); } Private voidlogpriority (String priority) {SYSTEM.OUT.PRINTLN ("Priority:" +Priority ); } }
Client calls:
Public classClient { Public Static voidMain (string[] args) {log log=NewDatabaseLog ();//Db-logLogerrorwrapper ErrorWrapper =NewLogerrorwrapper (log);//Level 1 Error level Db-logLogprioritywrapper Prioritywrapper =NewLogprioritywrapper (ErrorWrapper);//Special Priority 1 level error level Db-logErrorwrapper.seterrorlevel ("Level 1 Error"); Prioritywrapper.setpriority ("Special priority"); Prioritywrapper.write ("Hello world!"); }}
Output Result:
Priority: Special priority
Error level: Level 1 Error
Record Db-log:hello world!
From the code above, we can see that the DatabaseLog class only has the simplest log printing function, while the Logwrapper class implements log and holds a reference to log, while the subclass of Logwrapper has different extensions to the function of log. And the functionality of these extensions is completely transparent to the log.
From the call, we can see that in the Logwrapper (Decorator) subclass of the constructor, in addition to the subclass of the log, we can also pass in the Logwrapper own subclass, so that the decorative function can be superimposed. This is why we let the decorator abstract class implement the log interface.
So, if we need to add a function now, we just need to put a function of the decorated subclass on it, no need to add another subclass. It is good to have the flexibility of the runtime, the ability to combine functions at will when needed, without the need to statically write the various functional combinations to die in the code.
Decorator Decoration mode