PHP设计模式(八)装饰器模式Decorator实例详解【结构型】

yizhihongxing

下面是针对“PHP设计模式(八)装饰器模式Decorator实例详解【结构型】”文章的完整攻略。

1. 什么是装饰器模式Decorator?

装饰器模式(Decorator)是一种结构型设计模式,它允许你动态地将对象添加到现有对象中。使用装饰器模式,可以将一个或多个装饰器包装在对象上,从而改变其行为。当需要动态地将对象添加到现有对象中或从对象中删除对象时,可以使用装饰器模式。

2. 装饰器模式的主要组成部分

装饰器模式包含以下组成部分:

  • 抽象组件(Component):定义了一个抽象类,它是被装饰对象和所有具体装饰器的超类,提供了被装饰对象的基本行为,这些基本行为可以由具体装饰器来扩展。
  • 具体组件(ConcreteComponent):实现抽象组件类的具体类,提供基本行为。
  • 抽象装饰器(Decorator):定义了一个抽象类来装饰抽象组件或其具体子类,它可以是一个具体的类或一个抽象类。
  • 具体装饰器(ConcreteDecorator):实现抽象装饰器类的具体类,可以为装饰对象添加新的行为或扩展现有行为。

3. 装饰器模式的实例说明

下面我们通过两个具体的示例说明装饰器模式的使用。

示例1:制作不同口味的咖啡

假设我们正在制作咖啡并需要为其添加不同的口味:白糖、红糖和牛奶。在这个例子中,咖啡是抽象组件,而白糖、红糖和牛奶是具体装饰器。

首先,我们定义抽象组件:

    abstract class Coffee {
        protected $description = "Unknown Coffee";

        public function getDescription() {
            return $this->description;
        }

        public abstract function cost();
    }

接下来,我们定义具体组件:

    class Espresso extends Coffee {
        public function __construct() {
            $this->description = "Espresso";
        }

        public function cost() {
            return 1.99;
        }
    }

然后,我们定义抽象装饰器:

    abstract class CoffeeDecorator extends Coffee {
        public abstract function getDescription();
    }

接下来,我们定义具体装饰器:

    class Milk extends CoffeeDecorator {
        protected $coffee;

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

        public function getDescription() {
            return $this->coffee->getDescription() . ", Milk";
        }

        public function cost() {
            return $this->coffee->cost() + 0.20;
        }
    }

    class Sugar extends CoffeeDecorator {
        protected $coffee;

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

        public function getDescription() {
            return $this->coffee->getDescription() . ", Sugar";
        }

        public function cost() {
            return $this->coffee->cost() + 0.10;
        }
    }

    class RedSugar extends CoffeeDecorator {
        protected $coffee;

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

        public function getDescription() {
            return $this->coffee->getDescription() . ", RedSugar";
        }

        public function cost() {
            return $this->coffee->cost() + 0.15;
        }
    }

我们现在可以创建具体的咖啡对象,并动态地为其添加不同的装饰器:

    $beverage = new Espresso();
    echo $beverage->getDescription() . " $" . $beverage->cost();

    $beverage = new Milk($beverage);
    echo $beverage->getDescription() . " $" . $beverage-> cost();

    $beverage = new RedSugar($beverage);
    echo $beverage->getDescription() . " $" . $beverage->cost();

    $beverage = new Sugar($beverage);
    echo $beverage->getDescription() . " $" . $beverage->cost();

当我们执行这段代码时,输出结果如下:

    Espresso $1.99
    Espresso, Milk $2.19
    Espresso, Milk, RedSugar $2.34
    Espresso, Milk, RedSugar, Sugar $2.44

这说明我们成功地为咖啡添加了不同的口味。

示例2:动态添加属性到HTML标签

接下来,我们通过另一个示例来说明装饰器模式。假设我们需要动态地向HTML标签添加不同的属性,如class、id、style等。在此示例中,HTML标签是抽象组件,而属性是具体装饰器。

首先,我们定义抽象组件:

    abstract class HtmlTag {
        private $name;
        private $attributes;
        private $value;

        public function __construct($name) {
            $this->name = $name;
            $this->attributes = array();
            $this->value = "";
        }

        public function getName() {
            return $this->name;
        }

        public function setAttribute($attribute, $value) {
            $this->attributes[$attribute] = $value;
        }

        public function removeAttribute($attribute) {
            unset($this->attributes[$attribute]);
        }

        public function setValue($value) {
            $this->value = $value;
        }

        public function getValue() {
            return $this->value;
        }

        public function getAttributes() {
            return $this->attributes;
        }

        public abstract function render();
    }

接下来,我们定义具体组件:

    class HtmlInput extends HtmlTag {
        public function __construct($name) {
            parent::__construct($name);
        }

        public function render() {
            $html = "<input type=\"text\" name=\"{$this->getName()}\" value=\"{$this->getValue()}\" ";

            $attributes = $this->getAttributes();
            foreach($attributes as $attribute => $value) {
                $html .= "{$attribute}=\"{$value}\" ";
            }

            $html .= " />";

            return $html;
        }
    }

然后,我们定义具体装饰器:

    class HtmlClass extends HtmlTag {
        private $component;
        private $class;

        public function __construct(HtmlTag $component, $class) {
            $this->component = $component;
            $this->class = $class;
        }

        public function render() {
            $attributes = $this->component->getAttributes();
            $attributes['class'] = $this->class;
            $this->component->setAttributes($attributes);

            return $this->component->render();
        }
    }

    class HtmlId extends HtmlTag {
        private $component;
        private $id;

        public function __construct(HtmlTag $component, $id) {
            $this->component = $component;
            $this->id = $id;
        }

        public function render() {
            $attributes = $this->component->getAttributes();
            $attributes['id'] = $this->id;
            $this->component->setAttributes($attributes);

            return $this->component->render();
        }
    }

我们现在可以创建具体的HTML对象,并动态地为其添加不同的属性:

    $input = new HtmlInput("username");
    $input->setValue("admin");

    $input = new HtmlClass($input, "form-control");
    $input = new HtmlId($input, "username");

    echo $input->render();

当我们执行这段代码时,输出结果如下:

    <input type="text" name="username" value="admin" class="form-control" id="username"  />

这说明我们成功地为HTML标签动态添加了不同的属性。

4. 总结

本文通过以上两个示例详细讲解了装饰器模式的使用。要使用装饰器模式,需要遵循一些结构规则,并且需要理解抽象组件和装饰器之间的关系。如果需要动态地扩展一个对象,并且不能直接修改它的代码,那么应该考虑使用装饰器模式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:PHP设计模式(八)装饰器模式Decorator实例详解【结构型】 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • arcgis10.2之地图服务的发布、使用

    当然,我很乐意为您提供ArcGIS 10.2之地图服务的发布和使用攻略。以下是详细的步骤和示例: 步骤1:了解ArcGIS 10.2地图服务 ArcGIS 10.2地图服务是一种基于ArcGIS Server的Web服务,它可以将GIS数据发布到Web上,以便用户可以在Web浏览器中查看和查询地图数据。地图服务可以包含多个图层,每个图层可以包含多个要素类。 …

    other 2023年5月6日
    00
  • Java中不得不知的Collection接口与Iterator迭代器

    下面我就来讲解一下Java中Collection接口和Iterator迭代器的相关知识点。 什么是Java中的Collection接口 在Java中,Collection接口代表了一组对象,这些对象被称为元素。Collection接口定义了一些常用的操作,例如添加、删除、查找、枚举等。 Collection接口是Java集合框架的核心,主要有List、Set…

    other 2023年6月26日
    00
  • PowerShell ISE中代码转换大小写的技巧

    PowerShell ISE中代码转换大小写的技巧攻略 在PowerShell ISE中,你可以使用一些技巧来转换代码的大小写。下面是一些示例说明: 1. 使用ToUpper()和ToLower()方法 你可以使用ToUpper()和ToLower()方法来将代码转换为大写或小写。下面是一个示例: # 原始代码 $myString = \"Hell…

    other 2023年8月17日
    00
  • hbuilder打包app简易教程

    以下是“HBuilder打包APP简易教程的完整攻略”的详细说明,包括过程中的两个示例说明。 HBuilder打包APP简易教程 HBuilder是一款基于HTML5的开发工具,可以用于开发Web应用、移动应用等。以下是一份关于HBuilder打包APP的简易教程。 1. HBuilder基础知识 在开始使用HBuilder打包APP之前,我们需要掌握一些基…

    other 2023年5月10日
    00
  • linux如何部署nginx

    Linux如何部署nginx 在Linux服务器上部署nginx可以快速搭建一个高性能的web服务器,本文将介绍如何在Linux上安装和配置nginx。 步骤一:安装nginx 使用命令行工具登录到Linux服务器; 安装nginx,命令如下: sudo apt update sudo apt install nginx 等待安装完成,安装成功后启动ngin…

    其他 2023年3月28日
    00
  • Windows Server 2012下手动配置IIS的文件夹访问权限

    Windows Server 2012下手动配置IIS的文件夹访问权限的完整攻略 在Windows Server 2012中,IIS是一款常用的Web服务器软件。在使用IIS时,可能需要手动配置文件夹访问权限,以确保Web应用程序能够正常运行。本文将为您提供一份Windows Server 2012下手动配置IIS的文件夹访问权限的完整攻略,包括两个示例说明…

    other 2023年5月5日
    00
  • 电脑打不开网页怎么办 手把手教你解决上不了网问题

    电脑打不开网页怎么办 手把手教你解决上不了网问题 1. 检查网络连接 首先,当你无法打开网页时,应该检查你的电脑是否正常连接网络。你可以通过以下方式检查: 查看网络连接状态:在底部任务栏右侧找到网络图标,单击它,查看网络状态是否为已连接状态。 检查网线连接:如果你使用有线连接,你需要检查网线是否插好或连接是否松动。 重启路由器/猫:如果网络连接出现问题,你可…

    other 2023年6月27日
    00
  • C++类的静态成员变量与静态成员函数详解

    C++类的静态成员变量与静态成员函数详解 在C++中,类的静态成员变量和静态成员函数是与类本身相关联的,而不是与类的实例相关联的。它们在类的所有实例之间共享,并且可以通过类名直接访问,而不需要创建类的对象。 静态成员变量 静态成员变量是在类中声明的静态变量。它们在类的所有实例之间共享相同的值。静态成员变量必须在类的外部进行定义和初始化。 以下是一个示例: c…

    other 2023年8月16日
    00
合作推广
合作推广
分享本页
返回顶部