Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decorator design pattern vs. inheritance?

Tags:

I've read the decorator design pattern from Wikipedia, and code example from this site.

I see the point that traditional inheritance follows an 'is-a' pattern whereas decorator follows a 'has-a' pattern. And the calling convention of decorator looks like a 'skin' over 'skin' .. over 'core'. e.g.

I* anXYZ = new Z( new Y( new X( new A ) ) ); 

as demonstrated in above code example link.

However there are still a couple of questions that I do not understand:

  1. what does wiki mean by 'The decorator pattern can be used to extend (decorate) the functionality of a certain object at run-time'? the 'new ...(new... (new...))' is a run-time call and is good but a 'AwithXYZ anXYZ;' is a inheritance at compile time and is bad?

  2. from the code example link I can see that the number of class definition is almost the same in both implementations. I recall in some other design pattern books like 'Head first design patterns'. They use starbuzz coffee as example and say traditional inheritance will cause a 'class explosion' because for each combination of coffee, you would come up with a class for it.

    But isn't it the same for decorator in this case? If a decorator class can take ANY abstract class and decorate it, then I guess it does prevent explosion, but from the code example, you have exact # of class definitions, no less...

Would anyone explain?

like image 930
user1559625 Avatar asked Sep 12 '12 00:09

user1559625


People also ask

What is difference between decorator and inheritance?

With decorators, responsibilities can be added and removed at run-time simply by attaching and detaching them. In contrast, inheritance requires creating a new class for each additional responsibility (e.g., BorderedScrollableTextView, BorderedTextView).

Does decorator pattern use inheritance?

We use inheritance or composition to extend the behavior of an object but this is done at compile time and its applicable to all the instances of the class.

Is design pattern a inheritance concept?

The union design pattern is a structural pattern that depicts the inheritance relationship between a superclass and its subclasses. The superclass is an abstract representation of the union of all the subclasses. Due to this polymorphism, the subclasses can thus be used wherever the superclass is required.

What is a disadvantage of the decorator pattern?

Disadvantages. High degree of flexibility. High complexity of software (especially decorator interface) Expansion of function of classes without inheritance.


2 Answers

Let's take some abstract streams for example and imagine you want to provide encryption and compression services over them.

With decorator you have (pseudo code):

Stream plain = Stream(); Stream encrypted = EncryptedStream(Stream()); Stream zipped = ZippedStream(Stream()); Stream zippedEncrypted = ZippedStream(EncryptedStream(Stream()); Stream encryptedZipped = EncryptedStream(ZippedStream(Stream()); 

With inheritance, you have:

class Stream() {...} class EncryptedStream() : Stream {...} class ZippedStream() : Stream {...} class ZippedEncryptedStream() : EncryptedStream {...} class EncryptedZippedStream() : ZippedStream {...} 

1) with decorator, you combine the functionality at runtime, depending on your needs. Each class only takes care of one facet of functionality (compression, encryption, ...)

2) in this simple example, we have 3 classes with decorators, and 5 with inheritance. Now let's add some more services, e.g. filtering and clipping. With decorator you need just 2 more classes to support all possible scenarios, e.g. filtering -> clipping -> compression -> encription. With inheritance, you need to provide a class for each combination so you end up with tens of classes.

like image 63
Zdeslav Vojkovic Avatar answered Oct 21 '22 18:10

Zdeslav Vojkovic


In reverse order:

2) With, say, 10 different independent extensions, any combination of which might be needed at run time, 10 decorator classes will do the job. To cover all possibilities by inheritance you'd need 1024 subclasses. And there'd be no way of getting around massive code redundancy.

1) Imagine you had those 1024 subclasses to choose from at run time. Try to sketch out the code that would be needed. Bear in mind that you might not be able to dictate the order in which options are picked or rejected. Also remember that you might have to use an instance for a while before extending it. Go ahead, try. Doing it with decorators is trivial by comparison.

like image 22
Beta Avatar answered Oct 21 '22 17:10

Beta