What is the main advantage of having an iterator with two seperate classes, passing objects by reference as parameters?
Is it better to create an iterator with inheritance, rather than the non stop reference using and foreign method calling?
| SitePoint Sponsor |


What is the main advantage of having an iterator with two seperate classes, passing objects by reference as parameters?
Is it better to create an iterator with inheritance, rather than the non stop reference using and foreign method calling?



I assume that you are refering to the Decorator pattern used by a lot of the SPL Iterator classes.Originally Posted by Atealtha
it is better to use the Decorator as you can mix and match behaviours from different classes
Think about about this situation....
you have more flexiblity here as you can do something like ...PHP Code:class Pizza {
function __construct(Topping &$yumYum) {...}
}
interface Topping {
function addTopping();
}
class Bacon implements Topping {...}
class Chesse implements Topping {...}
class Tomato implements Topping {...}
class Ham implements Topping {...}
class Chicken implements Topping {...}
class PineApple implements Topping {...}
class SpicyCrapThatGivesYouTheRuns implements Topping {...}
new Pizza(new Cheese(new Tomato()));
OR
new Pizza(new Cheese(new Bacon(new PineApple())));
Basically, you can mix and match the toppings you want. With Inheritance, you have to state which you are extending from and therefore you can not mix and match things, unless you get a big class explosion.



I think I am missing something in the construct you propose, MiiJaySung, how does the constructor of the Topping class take other toppings as arguments?
As i see it, the Pizza class constructor's parameter is of type Topping which all the topping classes (Cheese, Bacon, etc.) implement. Thus, you can pass any class that implements the Topping interface to the Pizza constructor. Am i right?



Sorry, I should have made my question clearer. Yes, I understand that the constructor for the Pizza class takes a Topping object as an argument, what I do not understand is how the Topping class itself can take other toppings as implied by:
It seems to me that Cheese (a Topping) should be able to accept other toppings (tomato) as an argument in order for this to work, yet I see no constructor for the Topping class that explains how this is handled.PHP Code:new Pizza(new Cheese(new Tomato()));
![]()
I would assume that the constructors of the topping classes also have a Topping parameter, thus allowing you to "embed" them within one another





It just looks like a typo to me, the methods are the wrong way around. Should look like this imo:Originally Posted by ghurtado
the second is still a little iffy, because it implies that there will be a never ending chain of Toppings, becasue the last one will need to be constructed with a Topping argument too... Where I've done something like this, I've just thrown an exception if the paramater passed in is not the correct type (but simply do nothing if I get null).PHP Code:class Pizza {
function setTopping(){...}
}
interface Topping {
function __construct(Topping $yumYum) ;
}
The construct function might look like this:
hth,PHP Code:function __construct(Topping $yumYum) {
$this->decorates = $yumYum;
}
Douglas
Hello World



Thanks Doug, just the clarification I was looking for (I think)![]()





I don't believe that the pizza example is any good to be honest, if I was going to model a pizza I would use a collection, not a decorator. Using decorators (as far as I understand the pattern) it is like wrapping classes around a centeral class in a chain. With a collection, you have a generic base class and you add ther classes to the collection. That sounds much more like a pizza to me: you take the pizza base, and you add your toppings on top.
But then a real pizza is more complex than our simple model. Whenever I make one, I make a base to start off with, then I wrap that base in a layer of tomato paste, then add all the other toppings ontop of the tomato. I doubt that your average application would use only collections or only decorators. If you set up your classes well enough, you could easily decorate things before you add them to a collection. Once you start doing that, it becomes a question of what you want to do with your application code, rather than a theoretical discussion of what the options are. But then the theoretical abstraction might help you apply solutions to your application. Then again it might not. I guess you've got to learn like everyone else
Douglas
Hello World



This was just mock code to illustrate communication between classes. However if people need some example code for the constructor i will provide it.Originally Posted by ghurtado



I kinda agree here. My example was a little flawed as I didn't have time to think it through. I just used the first thing thaat came to mind. The arguement over whether it is a decorator or a collection that gets iterated over is debatable. Ideally, when you make a pizza you need to place toppings in a set order (for instance tomato paste at bottom, cheese, meat, vegtables, chillies spice and other cack). The decorator's "wrapping" behaviour matches this stack-like behaviour. On the other hand, decorators are very suited to pre / post processing. This is something you wouldn't really consider when you make a Pizza as you just slap the toppings on one after another.Originally Posted by DougBTX
Again this is debateable :-P When I make a pizza the model is a a lot more simple. I go to a supermarket, find a ready prepared pizza, and end up burning the crap out of it as I normally forget its in the ovenBut then a real pizza is more complex than our simple model. Whenever I make one, I make a base to start off with, then I wrap that base in a layer of tomato paste, then add all the other toppings ontop of the tomato
I was aware of this flaw as I posted the post. I wasn't too fussed as the idea of the post was to illustrate roughly the communication. I dislike the use of passing NULL as a default value as you can not do class typing in the function signature. Instead a better way is to have a setTopping(Topping &$flavour) method in place of the constrcutor. The method that processes toppings would need to check if the wrapped topping is NULL to determin the top most flavour.the second is still a little iffy, because it implies that there will be a never ending chain of Toppings, becasue the last one will need to be constructed with a Topping argument too..
Hopefully this clears up all the misunderstanding caused by my laziness to proof read my posts :-P


I came across a fairly good, in-depth explaination of why composition is sometimes preferable over inheritance.
http://www.oreilly.com/catalog/hfdes...apter/ch03.pdf
enjoy![]()
hummm, why did they use a decorator? just to show how you can use it?Originally Posted by Brenden Vickery
personally i would never use a decorator for such a problem..
cheers
Sike


Interesting, I thought they explained their choice fairly well. What would you do?
yeah the explanation is good and entertaining but my first guess would be a simple collection of items (nothing fancy i guess). i really don't see why this won't work. to be honest i don't work with patterns in the first place. they appear while i am refactoring my code (or not (; ). till now i never asked myself "what pattern would solve this problem best".Originally Posted by Brenden Vickery
cheers
Sike
ps. brendan what happened to your blog? tired of publishing stuff ?





Often I think "I've seen this problem before", in which case knowing the names of patterns which can help solve that problem can be useful. You can google the name of the pattern to quickly read about other people's experiences with it for example.Originally Posted by sike
I don't really need to ask the "what pattern" question most of the time: I have a good idea how I'm going to solve my problem anywayNoone ever said to use just one pattern at a time!
Douglas
Hello World


The reason this thread caught my attention and I was doing a little research on decorators vs inheritance is because of the offered solution to Helge in this thread: http://www.sitepoint.com/forums/showthread.php?t=211839
I decorated the eclipse iterator with a "DomainObjectIterator". I was wondering what if any benefit this had over inheriting from QueryIterator like this:
One advantage or disadvantage of using inheritance depending how you look at it is that in php5 with type hints this will work with a type of QueryIterator where the decorated solution wont.PHP Code:class DomainObjectIterator extends QueryIterator {
function DomainObjectIterator($mapper, $recordSet) {
$this->mapper = $mapper;
parent::QueryIterator($recordSet);
}
function getCurrent() {
return $this->mapper->load(parent::getCurrent());
}
}
Using inheritance also means that one less class needs to be instanciated.
Im undecided on which solution is the "better" solution. Anyone have thoughts on this?
I stopped blogging for all the usual reasons, too much work, too much golf, too much blah. Ill get back on it and post some stuff soon since you asked.
i use decorators rarely for the exact same reason : Interfaces and type hints in php5. if i really think a decorator suits best i setup a decorator base class implementing the appropiate interface (mostly to make type hinting work).Originally Posted by Brenden Vickery
on the other side i try my best to keep my object model as flat as possible...
hehe, ok. just asked out of interestOriginally Posted by Brenden Vickery
cheers
Sike





Have you heard of the "Design to an interface, not an implementation" line?Originally Posted by Brenden Vickery
It seems like it overlaps with the arguments for using decorators, though I'm not quite sure how to put it into words. Will have a go anyway:
When you decorate something, you keep the interface the same, but you don't directly extend the concrete class you had to start with, you just call its methods from the decorator. Here is some code:
What you have probably looks like this:PHP Code:interface SupportsIsHard {
function isHard();
}
class Concrete impliments SupportsIsHard {
function isHard() {
return true;
}
}
class Decorator impliments SupportsIsHard {
function isHard() {
return !$this->wrapped->isHard();
}
}
If you program to the interface, your type hinting should use the interface, not the concrete class.PHP Code:// bad
function testWithHammer(Concrete $object) {
if ($object->isHard()) {
return true;
}
}
Now, testWithHammer will not care whether $object is concrete or decorated, as long as it implements SupportsIsHard.PHP Code:// good
function testWithHammer(SupportsIsHard $object) {
if ($object->isHard()) {
return true;
}
}
I think it all boils down to the "extends is evil" thing, or rather "extends can be inflexible" if you want to get closer to the mark, but it does not sound half as good!
Later,
Douglas
Hello World


Originally Posted by DougBTX
Youre right of course, and that is why I was wrong in both the inheritance example and the decorator example. Neither conformed to the same interface as QueryIterator. The return type for getCurrent was changed from an array to an Object.Originally Posted by DougBTX
Using the QueryIterator example, it is best not to use inheritance so that a DomainObjectIterator can not be used with a QueryIterator type hint.
This doesnt answer the original question though. My advice would be to use either inheritance or a decorator as long as you keep the interface the same. Dont spend to much time thinking about this sort of thing until you have to, and then refactor to suit your needs.
Bookmarks