개념
데코레이터 패턴을 사용하면 구조를 변경하지 않고도 기존 개체에 새로운 기능을 추가할 수 있습니다. 이러한 유형의 디자인 패턴은 기존 클래스를 감싸는 래퍼 역할을 하는 구조적 패턴입니다.
이 패턴은 클래스 메소드 시그니처의 무결성을 유지하면서 원래 클래스를 래핑하고 추가 기능을 제공하는 데코레이션 클래스를 만듭니다.
UML 다이어그램
Role
추상 구성 요소 역할(Component): 추가를 허용할 준비가 된 개체를 표준화하기 위해 개체 인터페이스를 정의합니다. 책임 즉, 이러한 객체에 책임을 동적으로 추가할 수 있습니다.
ConcreteComponent: 데코레이터는 기능을 추가하기 위해 장식할 클래스를 정의합니다. 이 클래스의 개체에 몇 가지 책임을 추가할 수 있습니다
추상 데코레이터(Decorator): 구성 요소 구성 요소 개체를 가리키는 인스턴스를 유지하고 추상 구성 요소 역할 구성 요소 인터페이스와 일치하는 인터페이스를 정의합니다
콘크리트 데코레이터 역할(ConcreteDecorator): 구성 요소에 책임을 추가합니다.
적용 가능한 시나리오
객체에 동적으로 기능을 추가해야 하며, 이러한 기능은 동적으로 취소될 수 있습니다.
일부 기본 기능의 순열과 조합으로 생성되는 매우 많은 기능을 추가해야 하므로 상속관계가 비현실적입니다.
하위 클래스 생성 방법을 확장에 사용할 수 없는 경우. 어떤 경우에는 독립적인 확장이 많이 있을 수 있으며, 각 조합을 지원하기 위해 많은 수의 하위 클래스가 생성되어 하위 클래스 수가 폭발적으로 증가하게 됩니다. 또 다른 경우는 클래스 정의가 숨겨져 있거나 클래스 정의를 사용하여 하위 클래스를 생성할 수 없기 때문일 수 있습니다.
코드
<?php header('Content-type:text/html;charset=utf-8'); /** * 装饰器模式 */ /** * Interface IComponent 组件对象接口 */ interface IComponent { public function display(); } /** * Class Person 待装饰对象 */ class Person implements IComponent { private $_name; /** * Person constructor. 构造方法 * * @param $name 对象人物名称 */ public function __construct($name) { $this->_name = $name; } /** * 实现接口方法 */ public function display() { echo "装扮者:{$this->_name}<br/>"; } } /** * Class Clothes 所有装饰器父类-服装类 */ class Clothes implements IComponent { protected $component; /** * 接收装饰对象 * * @param IComponent $component */ public function decorate(IComponent $component) { $this->component = $component; } /** * 输出 */ public function display() { if(!empty($this->component)) { $this->component->display(); } } } /** * 下面为具体装饰器类 */ /** * Class Sneaker 运动鞋 */ class Sneaker extends Clothes { public function display() { echo "运动鞋 "; parent::display(); } } /** * Class Tshirt T恤 */ class Tshirt extends Clothes { public function display() { echo "T恤 "; parent::display(); } } /** * Class Coat 外套 */ class Coat extends Clothes { public function display() { echo "外套 "; parent::display(); } } /** * Class Trousers 裤子 */ class Trousers extends Clothes { public function display() { echo "裤子 "; parent::display(); } } /** * 客户端测试代码 */ class Client { public static function test() { $zhangsan = new Person('张三'); $lisi = new Person('李四'); $sneaker = new Sneaker(); $coat = new Coat(); $sneaker->decorate($zhangsan); $coat->decorate($sneaker); $coat->display(); echo "<hr/>"; $trousers = new Trousers(); $tshirt = new Tshirt(); $trousers->decorate($lisi); $tshirt->decorate($trousers); $tshirt->display(); } } Client::test();
실행 결과:
코트, 운동화, 드레서: 장산
티셔츠, 바지, 드레서: 리시