Using a decorator for caching purposes

In my previous post I  gave some examples on  how caching can evolve.   However , what annoys  me in the  second and third approach is that I have some extra code and  dependencies  which are not really related to my class.  The examples bellow detail how you can use a decorator to cache another class.

class Foo
{
    public function getExpensiveData()
    {
        return 1;
    }
 
    public function getNotSoExpensiveData()
    {
        return 0;
    }
 
    public function getUnbelievableExpensiveData($param)
    {
        //no hardware in the world can scale this
        sleep(1000);
        return 'string';
    }
} 
 
class Foo_Decorator_Exception extends Exception{};
 
class Foo_Decorator
{
    private $source = null;
 
    public function __construct(Foo $foo)
    {
        $this->source = $foo;
    }
 
    public function __call($method , $args)
    {
        $tag    = $method.serialize($args);
        $result = null;
        switch($method) {
            case 'getUnbelievableExpensiveData':
            case 'getExpensiveData':
                if ( !Cache::isCached($tag)) {
                    Cache::save( $this->_call($method , $args),$tag );
                }
 
                $result = Cache::load($tag);
                break;
            default :
                $result = $this->_call($method , $args);
                break;
 
        }
 
        return $result;
    }
 
    private function _call($method, $args)
    {
        if ( !is_object($this->source) ){
            throw new Foo_Exception("No delegate object set");
        }
 
        $delegate        = $this->source;
        $method_variable = array($delegate, $method);
        $callableName    = "";
 
        if ( is_callable( $method_variable, false, $callableName )){
            call_user_func_array($method_variable, $args);
        } else {
            throw new Foo_Exception("Function missing in both decorate and delegate object");
        }
 
    }
}

This entry was posted on Wednesday, November 18th, 2009 at 3:53 pm and is filed under tips. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

6 Responses to “Using a decorator for caching purposes”

  1. Giorgio Sironi Says:

    Good example, but I’d rather extract an interface when decorating.

  2. khelo Says:

    That’s a good practice , this example only pointed how you can cache a class with the use of an decorator . With few tweaks it can be used for any class.

    Of course there are other practices , but to make the example clear, this example does the job. Thank you for your feedback.

  3. Tweets that mention Webuml – Developer Notes » Blog Archive » Using a decorator for caching purposes -- Topsy.com Says:

    [...] This post was mentioned on Twitter by Flavio Luiz Mendes, deepak. deepak said: Using a decorator for caching purposes – http://www.webuml.com/blog/using-a-decorator-for-caching-purposes/62 [...]

  4. Twitted by deepakcs Says:

    [...] This post was Twitted by deepakcs [...]

  5. Rodney Says:

    Good solution. May want to consider using the Strategy pattern in place of the switch if the switch cases grow.

  6. khelo Says:

    thanks , I’ll do that.

Leave a Reply