tags:

views:

1273

answers:

3

Suppose there is a class called "Class_A", it has a member function called "func".

I want the "func" to do some extra work by wrapping Class_A in a decorator class.

$worker = new Decorator(new Original());

Can someone give an example? I've never used OO with PHP.

=======================================================

Thank you guys,you've provided a good demo for me!

Is the following version right?

class Decorator
{
    protected $jobs2do;

    public function __construct($string) {
        $this->jobs2do[] = $this->do;
    }

    public function do() {
        // ...
    }
}

The above code intends to put some extra work to a array.

+14  A: 

That is pretty easy, especially in a dynamically typed language like PHP:

class Text {

    protected $string;

    public function __construct($string) {
        $this->string = $string;
    }

    public function __toString() {
        return $this->string;
    }

}

class LeetText {

    protected $text;

    public function __construct($text) {
        $this->text = $text;
    }

    public function __toString() {
        return strtr($this->text->__toString(), 'eilto', '31170');
    }

}

$text = new LeetText(new Text('Hello world'));
echo $text; // H3110 w0r1d

You may want to have a look at the wikipedia article, too.

soulmerge
Great work :) +1 from me.
the_drow
Clean and simple +1 for me ;)
SleepyCod
Thanks,but how to pile a new member function to an array?seems my current version will cause warning.
Shore
Why $string and $text are not private?
Ivan Krechetov
You can make it private of course:)
Shore
public function __construct($text) is not clear. What does $text mean? How does one know from looking at it what should go in there? Mistakes are made too easy.
koen
Sorry, looks like I forgot to document my code snippet. What's the standard here on SO, anyway? Where can I find the coding guide for this forum? Do we use doxygen-style doc comments or javadoc? Or are there different guidlines for different languages?
soulmerge
+7  A: 

I would suggest that you also create a unified interface (or even an abstract base class) for the decorators and the objects you want decorated.

To continue the above example provided you could have something like:

interface IDecoratedText
{
    public function __toString();
}

Then of course modify both Text and LeetText to implement the interface.

class Text implements IDecoratedText
{
...//same implementation as above
}

class LeetText implements IDecoratedText
{    
    protected $text;

    public function __construct(IDecoratedText $text) {
        $this->text = $text;
    }

    public function __toString() {
        return str_replace(array('e', 'i', 'l', 't', 'o'), array(3, 1, 1, 7, 0), $this->text->toString());
    }

}

Why use an interface?

Because then you can add as many decorators as you like and be assured that each decorator (or object to be decorated) will have all the required functionality.

catchdave
That's why I said it is especially easy in PHP: You don't need such things there :)If you really want type-safety, you should be using another language.
soulmerge
I don't see the benefits of using an interface here
SleepyCod
Thanks,but how to pile a new member function to an array?seems my current version will cause warning.
Shore
The interface is not about type safety, per se. It helps debugging and provides clarity.Debugging example: you will get a "object does not implement the IDecoratedText interface" as opposed to the more generic "method does not exist" error.Better design:1. This design also clearly communicates to future developers (without extraneous comments) what type of objects this decorator works on (as opposed to a generic $text attribute).2. The interface makes it clear which methods future objects (either decorators or "decoratees") need to implement.
catchdave
+1  A: 

I second the use of an interface. It's especially informative with the decorator pattern. After all, it's not just the compiler/interpreter you're instructing, sometimes it's actually helpful to instruct other people as well, who're just trying to figure out what the h*ll it is that you're trying to accomplish ;)

JHollanti