Page 1 of 1
[56K WARN] difference between composites and decorators?
Posted: Tue Jan 16, 2007 4:31 am
by raghavan20
I see in composite pattern, one object tries to compose one or more of the same type and when i compared the uml diagram for decorator pattern from heads first design patterns with uml diagram for composite pattern from wikipedia.org they both look the same although i was never able to understand the decorator pattern properly.
Any light shed on this area should be very helpful for me and others. thanks.
Posted: Tue Jan 16, 2007 4:55 am
by jmut
Could you give us links to UML diagramms you refer.
From what I see in wikipedia...there are not the same.
Posted: Tue Jan 16, 2007 5:04 am
by raghavan20
jmut wrote:Could you give us links to UML diagramms you refer.
From what I see in wikipedia...there are not the same.
Decorator from Heads first design patterns
Composite from Wikipedia.org

Posted: Tue Jan 16, 2007 6:23 am
by johno
Decorator is used when you want to change behaviour of some class. For example
Code: Select all
abstract class UserFinder {
abstract public function findUserByFirstName($name);
}
class MySqlUserFinder extends UserFinder {
public function findUserByFirstName($name) {
// do select and return array of Users with name $name
}
}
// decorator
class UserFinderCache extends UserFinder {
private $originalFinder;
private $cachedResult;
public function __construct($finder) {
$this->originalFinder = $finder;
$this->cachedResult = false;
}
public function findUserByFirstName($name) {
if($this->cachedResult === false) {
$this->cachedResult = $this->originalFinder->findUserByFirstName($name);
}
return $this->cachedResult;
}
}
// basic usage
$finder = new MySQLUserFinder();
$finder->findUserByFirstName('John'); // first call to DB
$finder->findUserByFirstName('John'); // second call to DB
// decorator usage
$finder2 = new UserFinderCache($finder);
$finder->findUserByFirstName('John'); // first call to DB
$finder->findUserByFirstName('John'); // no call to DB, result from cachedResult
Composite patter isn something like a tree folder/file like structure.
Code: Select all
// component
abstract class Item {
abstract public function delete();
}
// leaf
class File extends Item {
private $file;
public function delete() {
@unlink($this->file);
}
}
// composite
class Folder extends Item {
private $items = array();
public function delete() {
foreach($this->items as $item) $item->delete();
}
public function addItem($item) {
$this->items[] = $item;
}
}
// usage
$root = new Folder();
$file1 = new File('afile.txt');
$root->addItem($file1);
$folder = new Folder();
$file2 = new File('afile2.txt');
$folder->addItem($file2);
$root->addItem($folder);
$root->delete(); // deletes all recursively
Got it?
Posted: Tue Jan 16, 2007 7:03 am
by raghavan20
thanks for your examples johno.
i guess decorator works like this:
we have one concrete object which we pass to a decorator which adds a new functionality to the passed object and this whole new object after decorated can be passed to another decorator to add other functionality and so forth.
the composite pattern is very clear from the example. but apart from the file example, where else do you think it can be implemented?
Posted: Tue Jan 16, 2007 7:11 am
by johno
raghavan20 wrote:i guess decorator works like this:
we have one concrete object which we pass to a decorator which adds a new functionality to the passed object and this whole new object after decorated can be passed to another decorator to add other functionality and so forth.
Yes, it can be done. Adding and/or modifying behavior on the fly thats decorator.
raghavan20 wrote:the composite pattern is very clear from the example. but apart from the file example, where else do you think it can be implemented?
Composite pattern is very useful for any tree hierarchies. Everywhere you have parent-child ralationship you can use composite. Nested categorization, page structure, XML, ... this list is endless.
Posted: Tue Jan 16, 2007 8:05 am
by Ollie Saunders
In my library is use composite so that fieldsets can store other fieldset or fields (although I call them containers and widgets). I've had a tricky time getting my head round the usefulness of the decorator pattern myself. Here are a couple of important conclusions I've come to about the decorator
- Decoration is not an alternative to inheritance, in that you can't use it everywhere where you can use inheritance. Decoration is actually quite limiting because you can really talk to the object you are decorating. All you can do it just stick stuff on the top of it.
- You should not use __call() and friends to make superclass decorators that can decorate any object. I read a blog post where the author listed about 4 good reasons why this is. Unfortunately I can neither find the post nor remember the points now except for the fact that you can't use reflection on a __call() implemented decorator. and thus...
- Decorator classes that just delegate every method call on to the object being decorated, despite the duplication, are not a design smell. Although this view comes very unnaturally to me.
- Where you can achieve something through decoration, i.e. you are just tacking on new stuff and not interfacing with the parent, you probably should use decoration because it allows you to extend that decoration separately from the object being decorated or possibly decorate a couple of similar objects with one decorator....in short you get a lot more flexibly of extension. Not needing to change something at runtime is not a good enough excuse to ignore decorators.