简体   繁体   中英

Decorator Pattern with added functions

I found this example for the decorator pattern in a text book.

装饰者模式示例

If we considered the object:

LockedStack MyStack = new LockedStack(new UndoStack(new Stack()))

How can I call the function undo on it?

MyStack.delegate.undo() won't work because delegate is private.

Does this example not work in this situation or am I missing something?

The purpose of the decorator pattern is:

to add new reponsibilities to objects dynamically.

If the new responsibility is embedded in the existing operations (eg push() and pop() ), the decorator will take care of forwarding the call to the decorated object before/after performing the additional responsibilities. It is then straightforward to chain decorators. You could for example achieve this with a slightly different design of the secure stack in which cryptographic methods would be private, and pushing/poping would secure the content on the flow:

在此处输入图像描述

If the new responsibilities are about additional operations , the design is not wrong (in fact GoF provides such an example). But it's another story when chaining decorators:

  • The decorator pattern does not provide any way to cumulate the new operations of all the intermediary decorators along the line. (If you really need this, consider rather the entity component system pattern )
  • The decorator pattern does not either provide an access to the decorated object, since this would lead client code to break the principle of least knowledge (law of demeter). Moreover you'd need to use risky down-castings.

The solution is then to use your decorator chain in another way: if you need a LockStack that offers lock operations and an UndoStack that offers undo, you'll need to keep a track of each of these decorator objects, and use the right object to obtain the corresponding operations:

UndoStack MyUndoStack = new UndoStack(new SecureStack (key,new Stack()));
LockedStack MyLockStack = new LockedStack(MyUndoStack); 
MyLockStack.lock();
MyUndoStack.undo();
MyLockStack.unlock();

This its less elegant but far more robust than creating a delegate getter and assuming in some code that a lockstack allways delegates to an undostack (hidden coupling).

In my opinion, this type of design is actually breaking the Decorator Pattern, since this is adding new behavior in each decorator. The purpose of decorator is to add new functionality transparently, eg,

BufferedReader in = new BufferedReader(new FileReader("foo.in"));

In above line, buffering is added without the need to invoke any new behavior.

I hope you get the point.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM