行为型

行为型解决的是不同对象之间的通信挑战。它们描述了不同的对象和类之间如何相互发送消息以使事情发生。以下是我们归类为行为型的模式列表。

  • 责任链模式

  • 命令模式

  • 解析器模式

  • 迭代器模式

  • 中介者模式

  • 备忘录模式

  • 观察者模式

  • 状态模式

  • 策略模式

  • 模板方法模式

  • 访问者模式

责任链模式

责任链模式通过使一个以上的对象以链式方式处理请求,将请求的发送方与接收方解耦。各种类型的处理对象可以动态地添加到链中。使用递归组成链,可以实现无限数量的处理对象。

下面是一个责任链模式的实现例子。

abstract class SocialNotifier {
    private $notifyNext = null;

    public function notifyNext(SocialNotifier $notifier) {
        $this->notifyNext = $notifier;
        return $this->notifyNext;
    }

    final public function push($message) {
        $this->publish($message);

        if ($this->notifyNext !== null) {
            $this->notifyNext->push($message);
        }
    }

    abstract protected function publish($message);
}

class TwitterSocialNotifier extends SocialNotifier {
    public function publish($message) {
        // Implementation...
    }
}

class FacebookSocialNotifier extends SocialNotifier {
    protected function publish($message) {
        // Implementation...
    }
}

class PinterestSocialNotifier extends SocialNotifier {
    protected function publish($message) {
        // Implementation...
    }
}

// Client
$notifier = new TwitterSocialNotifier();

$notifier->notifyNext(new FacebookSocialNotifier())
    ->notifyNext(new PinterestSocialNotifier());

$notifier->push('Awesome new product available!');

我们首先创建了一个抽象的SocialNotifier类,并实现了抽象方法publishnotifyNextpush方法。然后我们定义了TwitterSocialNotifierFacebookSocialNotifierPinterestSocialNotifier,它们都是对抽象SocialNotifier的扩展。客户端首先实例化TwitterSocialNotifier,然后是两次notifyNext调用,在调用最后的push方法之前,向它传递另外两个notifier类型的实例。

命令模式

命令模式将执行某些操作的对象与知道如何使用它的对象解耦。它通过封装以后执行某个操作所需的所有相关信息来实现。这意味着对象、方法名和方法参数的信息。

下面是一个命令模式的实现例子。

我们首先创建一个LightBulbCommand接口。然后我们定义了LightBulbControl类,它提供了两个简单的turnOn/turnOff方法。然后,我们定义了TurnOnLightBulbTurnOffLightBulb类,它们实现了LightBulbCommand接口。最后,客户端是用LightBulbControl的实例实例化TurnOffLightBulb对象,并对其调用执行方法。

解析器模式

解释器模式规定了如何评价语言语法或表达式。我们在定义解释器的同时,也定义了语言语法的表示方法。语言语法的表示使用复合类层次结构,其中规则被映射到类。然后,解释器使用表示法来解释语言中的表达式。

下面是一个解释器模式实现的例子。

我们首先创建一个MathExpression接口,有一个 interpret 方法。然后我们添加VariableLiteralSumProduct类,所有这些类都实现了MathExpression接口。然后,客户端从Product类中实例化,将LiteralSum的实例传递给它,并以一个 interpret 方法调用结束。

迭代器模式

迭代器模式用于遍历一个容器并访问其元素。换句话说,一个类可以遍历另一个类的元素。PHP对迭代器有一个本地支持,作为内置的\Iterator\IteratorAggregate接口的一部分。

下面是一个迭代器模式实现的例子。

首先创建了一个ProductIterator,它实现了标准的PHP \Iterator接口,然后我们添加了ProductCollection,它实现了标准的PHP \IteratorAggregate接口。客户端创建了一个ProductCollection的实例,通过addProduct方法调用将值堆积到其中,并循环浏览整个集合。

中介者模式

我们的软件中的类越多,它们的通信就越复杂。中介者模式通过将其封装成一个中介者对象来解决这种复杂性。对象不再直接通信,而是通过中介对象进行通信,因此降低了整体的耦合度。

下面是一个中介者模式实现的例子。

我们首先创建了一个带有多个方法的MediatorInterface,由ConcreteMediator类实现。然后,我们定义了抽象类Colleague,强制在下面的ColleagueAColleagueB类上实现doSomething方法。客户端首先实例化ConcreteMediator,并将其实例传递给ColleagueAColleagueB的实例,并根据这些实例调用doSomething方法。

备忘录模式

备忘录模式提供了对象还原功能。通过三个不同的对象来实现:originator、caretaker和memento,其中originator是保存以后还原所需的内部状态的对象。

以下是备忘录模式实现的一个例子。

我们首先创建一个Memento类,它将通过getState方法提供对象的当前状态。然后我们定义了Originator类,将状态推送给Memento。最后,客户端通过实例化Originator来扮演 caretaker 的角色,在它的几个状态之间进行杂耍,从Memento中保存和恢复这些状态。

观察者模式

观察者模式实现了对象之间一对多的依赖关系。持有依赖列表的对象被称为subject,而依赖者被称为observer。当subject对象改变状态时,所有的依赖对象都会得到通知并自动更新。

下面是一个观察者模式的实现例子。

我们首先创建一个Customer类,它实现了标准的PHP \SplSubject接口。然后我们定义了CustomerObserver类,它实现了标准的PHP \SplObserver接口。最后,客户端实例化CustomerCustomerObserver对象,并将CustomerObserver对象附加到Customer上。任何对姓名和电子邮件属性的改变都会被观察者捕获。

状态模式

状态模式封装了同一对象根据其内部状态而产生的不同行为,使对象看起来像是改变了它的类。

下面是一个状态模式的实现例子。

我们首先创建了一个Statelike接口,然后是实现该接口的StateLowerCaseStateMultipleUpperCaseStateMultipleUpperCase在它的writeName中加入了一点计数逻辑,所以它在两次调用之后就会启动新的状态。然后我们定义了StateContext类,我们将用它来切换上下文。最后,客户端实例化StateContext,并通过setState方法将StateLowerCase的一个实例传递给它,然后是几个writeName方法。

策略模式

策略模式定义了一个算法家族,每个算法都被封装起来,并可与该家族中的其他成员互换。

下面是一个策略模式的实现例子。

我们首先创建了一个PaymentStrategy接口,然后是实现它的具体类StripePaymentPayPalPayment。然后我们定义了Checkout类,并在capturePayment方法中加入了一些决策逻辑。最后,客户端实例化Checkout,通过其构造函数传递一定的金额。根据金额,Checkout内部在调用capturePayment时,会触发一个或另一个付款。

模板方法模式

模板方法模式在方法中定义了算法的程序骨架。它让我们通过使用类重载,重新定义算法的某些步骤,而不真正改变算法的结构。

下面是一个模板方法模式实现的例子。

我们首先创建了一个抽象的Game类,该类提供了所有封装游戏玩法的实际抽象方法。然后我们定义了MonopolyChess类,这两个类都是由Game类扩展而来,为每个类实现了特定的游戏方法game-play。客户端只需实例化MonopolyChess对象,对每个对象调用playOneGame方法。

访问者模式

访问者模式是一种将算法与其操作的对象结构分离的方法。因此,我们能够在现有的对象结构上添加新的操作,而不实际修改这些结构。

下面是一个访问者模式的实现例子。

我们首先创建一个RoleVisitorInterface,然后是RolePrintVisitor,它实现了RoleVisitorInterface本身。然后我们定义了一个抽象类Role,它有一个接受方法来接受RoleVisitorInterface的参数类型。我们进一步定义了具体的UserGroup类,这两个类都是从Role扩展而来的。客户端实例化UserGroupRolePrintVisitor;将 visitor 传入UserGroup实例的accept方法调用。

最后更新于