>  기사  >  백엔드 개발  >  PHP의 데코레이터 패턴에 대한 간략한 토론

PHP의 데코레이터 패턴에 대한 간략한 토론

青灯夜游
青灯夜游앞으로
2021-06-23 18:40:392830검색

데코레이터 패턴을 사용하면 구조를 변경하지 않고도 기존 객체에 새로운 기능을 추가할 수 있습니다. 이 기사에서는 PHP의 데코레이터 패턴을 안내하고 데코레이터의 이점과 가장 적합한 시나리오를 소개합니다.

PHP의 데코레이터 패턴에 대한 간략한 토론

팩토리 패턴이 끝났으니 다른 패턴을 공부해 볼까요? 혹시 여성복을 입어보신 분 있으신가요? 여성 프로그래머가 많다고 합니다. 사실 오늘날의 데코레이터 패턴은 메이크업과 매우 유사합니다. 나는 Program Yuan MM이 여기 있다면 이 디자인 패턴을 즉시 설명할 수 있다고 믿습니다.

고프 클래스 다이어그램 및 설명

장식이라는 두 단어는 일단 메이크업으로 바꿔보겠습니다. 먼저 얼굴을 정돈한 다음 파운데이션을 바르고 화장을 하세요. 아침에 출근할 때는 옅은 화장을 해도 되고, 퇴근하고 놀러 갈 때는 짙은 화장을 해도 됩니다. . 물론 프로그래머들이 퇴근하는 시간은 공교롭게도 하반기 심야쇼 시간과 맞먹는다. 그런데 아무리 화장을 해도 얼굴은 자기 얼굴이고, 남들이 알아보지 못하는 다른 사람으로 변신할 수도 있지만, 그래도 얼굴은 자기 얼굴이다. 객체(얼굴)에 다양한 장식(화장)을 하여 얼굴을 더 돋보이게 만드는(책임감 증가) 데코레이터입니다.

GoF 정의: 기능 추가 측면에서 일부 추가 책임을 동적으로 추가하는 측면에서 데코레이터 패턴은 하위 클래스를 생성하는 것보다 더 유연합니다.

GoF 클래스 다이어그램:

PHP의 데코레이터 패턴에 대한 간략한 토론

코드 구현:

interface Component{
    public function operation();
}

class ConcreteComponent implements Component{
    public function operation(){
        echo "I'm face!" . PHP_EOL;
    }
}

이는 매우 간단한 인터페이스이자 구현입니다. 여기서는 특정 구현 클래스를 얼굴로 간주합니다.

abstract class Decorator implements Component{
    protected $component;
    public function __construct(Component $component){
        $this->component = $component;
    }
}

추상 데코레이터 클래스는 Component 인터페이스를 구현하지만 Operation() 메서드는 구현하지 않으므로 하위 클래스에서 구현할 수 있습니다. 여기서는 주로 나중에 장식할 Component에 대한 참조를 저장합니다. 위의 특정 카테고리에 맞춰 얼굴 메이크업을 준비할 예정이에요!

class ConcreteDecoratorA extends Decorator{
    public $addedState = 1; // 没什么实际意义的属性,只是区别于ConcreteDecoratorB

    public function operation(){
        echo $this->component->operation() . "Push " . $this->addedState . " cream!" . PHP_EOL;
    }
}
class ConcreteDecoratorB extends Decorator{
    public function operation(){
        $this->component->operation();
        $this->addedBehavior();
    }

    // 没什么实际意义的方法,只是区别于ConcreteDecoratorA
    public function addedBehavior(){
        echo "Push 2 cream!" . PHP_EOL;
    }
}

콘크리트 장식가 두 명. 저는 여기 크림을 두 번 발랐어요. 역시 저는 순수한 남자이고 메이크업에 대해 잘 모르는 편이에요. 첫 번째 단계는 파운데이션을 바르는 것 같죠? 하지만 이번에는 두 명의 데코레이터가 달성한 것이 얼굴에 두 겹의 서리를 바르는 것입니다.

  • 특정 ConcreteComponent 객체를 패키징했다는 코드를 보면 알 수 있습니다
  • 더 나아가서 실제로는 그 Operation() 메서드를 두 번, 매번 앞쪽에 패키징했습니다. 한 번에 조금씩 추가합니다
  • A와 B 데코레이터에 추가된 속성과 메서드에 집착하지 마세요. 이는 GoF 클래스 다이어그램에서 두 데코레이터가 동일하지 않다는 것을 구별하기 위해 사용되는 것입니다. 다른 많은 작업을 수행할 수 있습니다. Component 객체에는 반드시 하나의 메소드(Operation())만 있는 것은 아닙니다. 객체의 메소드 전체 또는 일부를 선택적으로 꾸밀 수 있습니다. Direct 하위 클래스는 모두 다시 작성할 수 없는 것 같습니다. 이 모든 문제에? 친애하는, 결합의 개념을 이해하십시오. 우리의 데코레이터 상위 클래스에는 자체적으로 분리되는 실제 객체에 대한 참조가 포함되어 있습니다. 데코레이터를 직접 인스턴스화하여 직접 사용하지 마세요. 이해하다? 이점은 무엇입니까? 감히 기존 시스템의 클래스와 메소드를 무작위로 변경할 수 있습니까? 전 애인이 작성한 멋진 코드에 새로운 기능을 추가하고 싶다면 데코레이터를 사용해 보는 것이 좋을 것입니다. 놀라운 일이 될 것입니다!
  • 이 휴대폰 일은 특정 Mi, 특정 O, 특정 Wei가 할 수 없습니다. 알았어 친구, 가서 휴대폰 케이스 만들기에 집중하세요! 자 먼저 투명한 쉘(컴포넌트)을 준비했는데 좀 보기 흉한데 어찌할 수가 없네요. 누가 저를 형편없다고 합니까? 특정 미터에 다양한 단색(DecoratorA1)을 추가하고 뒷면에 ​​다양한 색상의 식물(DecoratorB1)을 인쇄합니다. 최근 교통 신호를 받는 특정 O의 휴대폰이 마음에 들어서 휴대폰 케이스에 다양한 색상을 사용하겠습니다. . 눈부신 색상(DecoratorA2)과 연예인 만화 아바타(DecoratorB2) 마지막으로 휴대폰이 업계 트렌드를 주도하기 시작한 것 같습니다. 이 병풍이 휴대폰 케이스 판매 사업을 망칠 것 같지 않나요? ! 알았어, 내가 안 해줄 테니까, 그냥 미 누님이랑 오 누누랑 놀아라! !

전체 코드: 데코레이터 패턴

https://github.com/zhangyue0503/designpatterns-php/blob/master/04.designator/source/ decorator.php

계속 SMS 보내기 , 여러 SMS 운영자의 문제를 해결하기 위해 공장 모드를 사용하기 전에. 이번에는 문자 메시지 콘텐츠 템플릿의 문제를 해결해야 합니다. 홍보 문자 메시지에는 최신 광고법에 따라 '국내 1위', '세계 1위' 등의 단어를 사용할 수 없습니다. 물론 일부 야만적인 용어도 사용할 수 없습니다.

现在的情况是这样的,我们有一个很早之前的短信模板类,里面的内容是固定的,老系统依然还是使用这个模板,老系统是面对的内部员工,对语言内容的要求不高。而新系统则需要向全网发送,也就是内外部的用户都要发送。这时,我们可以用装饰器模式来对老系统的短信模板进行包装。其实说简单点,我们就是用装饰器来做文本替换的功能。好处呢?当然是可以不去改动原来的模板类中的方法就实现了对老模板内容的修改扩展等。

短信发送类图:

PHP의 데코레이터 패턴에 대한 간략한 토론

完整源码:短信发送装饰器方法

https://github.com/zhangyue0503/designpatterns-php/blob/master/04.decorator/source/message-decorator.php

<?php
// 短信模板接口
interface MessageTemplate
{
    public function message();
}

// 假设有很多模板实现了上面的短信模板接口
// 下面这个是其中一个优惠券发送的模板实现
class CouponMessageTemplate implements MessageTemplate
{
    public function message()
    {
        return &#39;优惠券信息:我们是全国第一的牛X产品哦,送您十张优惠券!&#39;;
    }
}

// 我们来准备好装饰上面那个过时的短信模板
abstract class DecoratorMessageTemplate implements MessageTemplate
{
    public $template;
    public function __construct($template)
    {
        $this->template = $template;
    }
}

// 过滤新广告法中不允许出现的词汇
class AdFilterDecoratorMessage extends DecoratorMessageTemplate
{
    public function message()
    {
        return str_replace(&#39;全国第一&#39;, &#39;全国第二&#39;, $this->template->message());
    }
}

// 使用我们的大数据部门同事自动生成的新词库来过滤敏感词汇,这块过滤不是强制要过滤的内容,可选择使用
class SensitiveFilterDecoratorMessage extends DecoratorMessageTemplate
{
    public $bigDataFilterWords = [&#39;牛X&#39;];
    public $bigDataReplaceWords = [&#39;好用&#39;];
    public function message()
    {
        return str_replace($this->bigDataFilterWords, $this->bigDataReplaceWords, $this->template->message());
    }
}

// 客户端,发送接口,需要使用模板来进行短信发送
class Message
{
    public $msgType = &#39;old&#39;;
    public function send(MessageTemplate $mt)
    {
        // 发送出去咯
        if ($this->msgType == &#39;old&#39;) {
            echo &#39;面向内网用户发送&#39; . $mt->message() . PHP_EOL;
        } else if ($this->msgType == &#39;new&#39;) {
            echo &#39;面向全网用户发送&#39; . $mt->message() . PHP_EOL;
        }

    }
}

$template = new CouponMessageTemplate();
$message = new Message();

// 老系统,用不着过滤,只有内部用户才看得到
$message->send($template);

// 新系统,面向全网发布的,需要过滤一下内容哦
$message->msgType = &#39;new&#39;;
$template = new AdFilterDecoratorMessage($template);
$template = new SensitiveFilterDecoratorMessage($template);

// 过滤完了,发送吧
$message->send($template);

说明

  • 装饰器的最大好处:一是不改变原有代码的情况下对原有代码中的内容进行扩展,开放封闭原则;二是每个装饰器完成自己的功能,单一职责;三是用组合实现了继承的感觉;
  • 最适用于:给老系统进行扩展
  • 要小心:过多的装饰者会把你搞晕的
  • 不一定都是对同一个方法进行装饰,其实装饰者应该更多的用于对对象的装饰,对对象进行扩展,这里我们都是针对一个方法的输出进行装饰,但仅限此文,装饰器的应用其实更加广泛
  • 装饰器的特点是全部都继承自一个主接口或类,这样的好处就是返回的对象是相同的抽象数据,具有相同的行为属性,否则,就不是装饰之前的对象,而是一个新对象了
  • 有点不好理解没关系,我们这次的例子其实也很勉强,这个设计模式在《Head First设计模式》中有提到Java的I/O系列接口是使用的这种设计模式:FileInputStream、LineNumberInputStream、BufferInputStream等
  • Laravel框架中的中间件管道,这里其实是多种模式的综合应用,其中也应用到了装饰器模式:Laravel HTTP——Pipeline 中间件装饰者模式源码分析
  • 另外在Laravel中,日志处理这里也是对Monolog进行了装饰,有兴趣的同学可以去了解下

推荐学习:《PHP视频教程

위 내용은 PHP의 데코레이터 패턴에 대한 간략한 토론의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제