Using Lists Instead of Decorator Pattern?
A Decorator Pattern use case from "Head First: Design Patterns" book made me have this question. I'll try to write it down:
It's a coffee shop system with some coffees and a lot of condiments you can put in them (for an extra cost), you need to be able to order and charge for a coffee with any condiments the costumer desires, and to avoid having total mayhem (eg booleans to keep track of the condiments) Decorator Pattern is used. We have an abstract Beverage class, each type of coffee as concrete components and each condiment as concrete decorators wrapping up a Beverage, like this:
And so we have the following process returning a coffee cost:
My question is: Why not implement this with Lists instead of the Decorator? We could have a list of Condiment in each Beverage and calculate the cost by iterating through the List. To order a coffee we would just have to instantiate it once and add the desired condiments, avoiding declarations like:
// Using second image example
Beverage beverage = new DarkRoast(beverage);
beverage = new Mocha(beverage);
beverage = new Whip(beverage);
In addition to that we would have more flexibility for operations like giving discount for a coffee not including it's condiments, once we won't have decorators wrapping up the coffee. This is a matter that have been long studied, I know I'm missing something or maybe I got something wrong, so if you have any thoughts on this I would love to know and discuss it further.
You should distinguish data from behaviour.
A decorator is a layer of indirection dealing with a very specific problem. The data (in terms of types, contracts, protocols etc) stays the same, but you get more flexibility regarding the implementation. With a decorator, you can reuse existing functionality and start adding changes - in conjunction with an adapter in place, you can basically slowly start migrating from pone API to a different one and stay compatible.
Lists should only be responsible for providing access to the contained data in a specific way. Performing tasks on the data / processing the data contained by the lists should be done by function / objects / classes with different responsibilities.
What you are telling is a way to calculate the total cost of the beverage. In more general terms you are proposing an alternative way to merge & execute the main behavior of each of the derived objects supposed by the Decorator Pattern, by adding up them into a list. And it is not quite an OO approach too.
But the original intent of Decorator Pattern goes to a much wider perspective other than that. It is Adding extended functionalities to an object dynamically . Which means I have some object O1
& I want it to convert it into another object O2
with extended functionality & yet to be those 2 are interchangeable.
So it is about how we can manage the Object Evolution against the Object Lifecycle . Hope you got the idea. :))
Decorator
pattern is about decorating ( enhancing ) an object with additional features at runtime.
Suppose you already have a class, lets call it class A
which implements an interface IA
. Now if there is a requirement of adding an additional feature for which we want it to have a method , someAlignFeatureToA()
which was not there in A
. Now you have an option of extending the class A
. Another approach is Composition
which should be favoured over Inheritance
. You can wrap the object of class A
in another class B
implwmenting the same Interface
as of A
ie IA
. This way for the client code it would be easy to accept the object of class B as it has the same interface as of A. (Assumption is the code is well written which depends on the Abstractions (interface IA
) and not on concrete classes like class A
).
This way the inheritance chain is not too long and you can add additional features at runtimw easily.
链接地址: http://www.djcxy.com/p/39136.html上一篇: 为什么不std :: count和std :: find优化使用memchr?
下一篇: 使用列表而不是装饰模式?