使用PHP製作樣版引擎-極簡範例3,使用 Decorator 裝飾者(包裝器)模式

先問自已 2 個問題
什麼是 Decorator 裝飾者(包裝者)模式?
Decorator 裝飾者(包裝者)模式可以運用在什麼地方?

根據書上範例架構重新修改之前的範例

建立一個抽象類別 IComponent

abstract class IComponent
{
    protected $site;
    public abstract function getSite();
}

再建立一個抽象類別 Decorator 繼承剛剛建立的抽象類別 IComponent,所以這裡不能實作任何方法

abstract class Decorator extends IComponent
{
    //public abstract function getSite();
}

建立基本頁面類別,這裡只給它網頁抬頭宣告

class BasicSite extends IComponent
{
    public function __construct()
    {
        $this->site = "<!DOCTYPE HTML>";
    }

    public function getSite()
    {
        return $this->site;
    }
}

建立 3 個類別,分別是 Header, Body, Footer 用來表示網頁內容

class Header extends IComponent
{
    protected $header;

    public function __construct()
    {
        $this->header = <<<HTML

<html>
<head>
	<meta http-equiv="content-type" content="text/html" />
	<title>極簡頁面</title>
</head>
<body>

HTML;
    }

    public function getSite()
    {
        return $this->header;
    }
}

class Body extends IComponent
{
    protected $body;

    public function __construct()
    {
        $this->body = "Hi,這是極簡頁面的測試";
    }

    public function getSite()
    {
        return $this->body;
    }
}

class Footer extends IComponent
{
    protected $footer;

    public function __construct()
    {
        $this->footer = <<<HTML

</body>
</html>
HTML;
    }

    public function getSite()
    {
        return $this->footer;
    }
}

建立一個類別,這裡實作裝飾者如何包裝原有的 BasicSite 類別,在原有的 BasicSite 加入其它類的功能

class HtmlPage
{
    private $baseHtml;
    private $header;
    private $body;
    private $footer;
    private $htmlPage;

    public function __construct()
    {
        $this->baseHtml = new BasicSite();
        $this->header = new Header();
        $this->body   = new Body();
        $this->footer = new Footer();
    }

    public function getHtml()
    {
        $this->htmlPage  = $this->baseHtml->getSite();
        $this->htmlPage .= $this->header->getSite();
        $this->htmlPage .= $this->body->getSite();
        $this->htmlPage .= $this->footer->getSite();

        return $this->htmlPage;
    }
}

客戶端程式碼

class Client
{
    private $htmlPage;

    public function __construct()
    {
        $this->htmlPage = new HtmlPage();
        echo $this->htmlPage->getHtml();
    }
}

$worker = new Client();

Browser結果
Hi,這是極簡頁面的測試

<!DOCTYPE HTML>
<html>
<head>
	<meta http-equiv="content-type" content="text/html" />
	<title>極簡頁面</title>
</head>
<body>
Hi,這是極簡頁面的測試
</body>
</html>