Decorator Design Pattern

Decorator is a structural design pattern that allows you to attach new behaviors to objects by placing these objects inside special wrapper objects that contain the behaviors.

Extending a class is the first thing that comes to mind when you need to modify the behavior of an object. However, inheritance has several important caveats that you should be aware of. Inheritance is static. You cannot modify the behavior of an existing object at run time. You can only replace the entire object with one created from a different subclass. Subclasses can have only one main class. In most languages, inheritance does not allow a class to inherit behaviors from multiple classes at the same time.

One of the ways to overcome these caveats is through aggregation or composition rather than inheritance. Both alternatives work in much the same way: one object has a reference to another and delegates some work to it, whereas with inheritance, the object itself can do that work, inheriting the behavior of its superclass.

Lets look at the examples I created as below.

Sample PHP

<?php

/**
 * The interface that must be implemented by concrete class or decorator class
 * Many methods might exist in a real world application.
 */
interface Home
{
    public function setup();
}

/**
 * An example simple concrete class implementing the interface through the setup method.
 */
class ModernHome implements Home
{
    public $addon;

    public function setup()
    {
        $this->addon[] = "Added extra bed room";
    }
}

/**
 * Here is the base decorator class referncing the home interface.
 * Implementations don't exist here as this is the scheme of the concrete classes that will extend to it.
 */
abstract class ModernHomeDecorator implements Home
{
    protected $home;

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

    abstract public function setup();
}

/**
 * Concrete decorator classes extending the  basedecorator(wrapping the original ModernHome Instance).
 */
class CinemaDecorator extends ModernHomeDecorator
{
    public function setup()
    {
        $this->home->setup();
        $this->home->addon[] = "added mini cinema";
        $this->addon = $this->home->addon;
    }
}


class PoolDecorator extends ModernHomeDecorator
{
    public function setup()
    {
        $this->home->setup();
        $this->home->addon[] = "added pool";
        $this->addon = $this->home->addon;
    }
}


/**
 * Clients just have to pass the modernhome instance to each decorator class that they want.
 * We can see here it is wrapping step by step. ModenHome is wrapped by cinema. Afterwards, cinema is wrapped by pool.
 * Array ( [0] => Added extra bed room [1] => added mini cinema [2] => added pool )
 */

$home = new ModernHome();
$home = new CinemaDecorator($home);
$home = new PoolDecorator($home);
$home->setup();

print_r($home->addon);

Sample C#

using System;

namespace HelloWorld
{

    /**
     * The interface that must be implemented by concrete class or decorator class
     * Many methods might exist in a real world application.
     */
    abstract class Home
    {
        public abstract string setup();
    }

    /**
     * An example simple concrete class implementing the interface through the setup method.
     */
    class ModernHome : Home
    {
        public override string setup()
        {
            return "ModernHome";
        }
    }

    /**
     * Here is the base decorator class referncing the home interface.
     * Implementations don't exist here as this is the scheme of the concrete classes that will extend to it.
     * we have a condition here to do the wrapping process.
     */
    abstract class Decorator : Home
    {
        protected Home _Home;

        public Decorator(Home Home)
        {
            this._Home = Home;
        }


        public override string setup()
        {
            if (this._Home != null)
            {
                return this._Home.setup();
            }
            else
            {
                return string.Empty;
            }
        }
    }

    /**
     * Concrete decorator classes extending the  basedecorator(wrapping the original ModernHome Instance).
     */
    class CinemaDecorator : Decorator
    {
        public CinemaDecorator(Home comp) : base(comp){}

        
        public override string setup()
        {
            return $"CinemaDecorator({base.setup()})";
        }
    }

    class PoolDecorator : Decorator
    {
        public PoolDecorator(Home comp) : base(comp){}

        public override string setup()
        {
            return $"PoolDecorator({base.setup()})";
        }
    }


    /**
     * Clients just have to pass the modernhome instance to each decorator class that they want.
     * We can see here it is wrapping step by step. ModenHome is wrapped by cinema. Afterwards, cinema is wrapped by pool.
     * PoolDecorator(CinemaDecorator(ModernHome))
     */
    class Program
    {
        static void Main(string[] args)
        {

            var moden = new ModernHome();
            CinemaDecorator cinema = new CinemaDecorator(moden);
            PoolDecorator pool = new PoolDecorator(cinema);
            Console.WriteLine(pool.setup());
            
        }
    }

}

By Yuuma.



アプリ関連ニュース

お問い合わせはこちら

お問い合わせ・ご相談はお電話、またはお問い合わせフォームよりお受け付けいたしております。

tel. 06-6454-8833(平日 10:00~17:00)

お問い合わせフォーム