概述

桥接模式是一种结构型设计模式,它将抽象部分和实现部分分离,使它们可以独立变化。通过桥接模式,可以将抽象部分和实现部分进行组合,而不是继承关系,从而使系统更加灵活。

适用场景

桥接模式适用于以下情况:

  • 当一个类存在多个维度的变化,且这些维度可以独立变化时。
  • 当希望在抽象部分和实现部分之间建立一个稳定的关联关系,而不希望二者紧密耦合时。
  • 当希望在运行时动态地切换抽象部分和实现部分的时候。

结构

桥接模式由以下组件组成:

  • 抽象类(Abstraction):抽象类定义了抽象部分的接口,并维护一个指向实现部分的引用。
  • 扩展抽象类(RefinedAbstraction):扩展抽象类继承自抽象类,扩展了抽象部分的功能。
  • 实现接口(Implementor):实现接口定义了实现部分的接口。
  • 具体实现类(ConcreteImplementor):具体实现类实现了实现接口,提供具体的实现。

示例

<?php

// 抽象类
abstract class Vehicle
{
    protected $implementor;

    public function __construct(Workshop $implementor)
    {
        $this->implementor = $implementor;
    }

    abstract public function manufacture();
}

// 扩展抽象类
class Car extends Vehicle
{
    public function manufacture()
    {
        echo "Car ";
        $this->implementor->work();
    }
}

class Bike extends Vehicle
{
    public function manufacture()
    {
        echo "Bike ";
        $this->implementor->work();
    }
}

// 实现接口
interface Workshop
{
    public function work();
}

// 具体实现类
class Produce implements Workshop
{
    public function work()
    {
        echo "produced";
    }
}

class Assemble implements Workshop
{
    public function work()
    {
        echo "assembled";
    }
}

// 客户端代码
$car = new Car(new Produce());
$car->manufacture(); // Output: Car produced

$bike = new Bike(new Assemble());
$bike->manufacture(); // Output: Bike assembled

在上面的示例中,我们给出了一个桥接模式的示例实现。其中,抽象类(Vehicle)定义了抽象部分的接口,并维护一个指向实现部分的引用。扩展抽象类(Car和Bike)继承自抽象类,并扩展了抽象部分的功能。实现接口(Workshop)定义了实现部分的接口,具体实现类(Produce和Assemble)实现了实现接口,提供具体的实现。

通过使用桥接模式,我们可以将抽象部分和实现部分独立变化,通过组合的方式将它们进行连接。这样一来,当抽象部分或实现部分发生变化时,它们可以独立变化,而不会相互影响。

概述

迭代器模式是一种行为型设计模式,它提供一种遍历聚合对象中各个元素的方法,而无需暴露聚合对象的内部表示。通过使用迭代器模式,可以在不暴露聚合对象内部结构的情况下,让客户端代码能够逐个访问聚合对象中的元素。

适用场景

迭代器模式适用于以下情况:

  • 当你需要遍历一个聚合对象的元素,但又不希望暴露聚合对象的内部结构给客户端代码时。
  • 当你希望提供多种遍历方式,而不仅限于顺序遍历时。
  • 当你希望能够让聚合对象的表示和遍历算法独立变化时。

结构

迭代器模式由以下组件组成:

  • 迭代器接口(Iterator):迭代器接口定义了遍历聚合对象元素的方法。
  • 具体迭代器(ConcreteIterator):具体迭代器实现了迭代器接口,提供对聚合对象的顺序遍历。
  • 聚合对象接口(Aggregate):聚合对象接口定义了创建具体迭代器对象的方法。
  • 具体聚合对象(ConcreteAggregate):具体聚合对象实现了聚合对象接口,创建相应的具体迭代器对象。

示例

<?php

// 迭代器接口
interface Iterator
{
    public function hasNext();
    public function next();
}

// 具体迭代器
class ConcreteIterator implements Iterator
{
    private $collection;
    private $position = 0;

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

    public function hasNext()
    {
        return $this->position < count($this->collection);
    }

    public function next()
    {
        $item = $this->collection[$this->position];
        $this->position++;
        return $item;
    }
}

// 聚合对象接口
interface Aggregate
{
    public function createIterator();
}

// 具体聚合对象
class ConcreteAggregate implements Aggregate
{
    private $collection = [];

    public function addItem($item)
    {
        $this->collection[] = $item;
    }

    public function createIterator()
    {
        return new ConcreteIterator($this->collection);
    }
}

// 客户端代码
$aggregate = new ConcreteAggregate();
$aggregate->addItem("Item 1");
$aggregate->addItem("Item 2");
$aggregate->addItem("Item 3");

$iterator = $aggregate->createIterator();
while ($iterator->hasNext()) {
    echo $iterator->next() . PHP_EOL;
}

在上面的示例中,我们给出了一个迭代器模式的示例实现。其中,我们定义了迭代器接口(Iterator)和具体迭代器(ConcreteIterator)的实现。接着,我们定义了聚合对象接口(Aggregate)和具体聚合对象(ConcreteAggregate)的实现。最后,我们创建了一个具体聚合对象并添加了一些元素,然后通过调用聚合对象的createIterator方法来创建具体迭代器对象,并使用迭代器逐个访问聚合对象中的元素。

概述

代理模式是一种结构型设计模式,它允许通过创建一个代理对象来控制对其他对象的访问。代理对象充当了客户端和实际对象之间的中介,可以在访问实际对象之前或之后添加额外的逻辑。

适用场景

代理模式适用于以下情况:

  • 当你想要在访问一个对象时添加额外的逻辑,而不改变原始对象的代码。
  • 当你需要对原始对象进行访问控制,例如权限验证、缓存等。
  • 当你希望延迟实例化一个对象,直到真正需要它的时候。

结构

代理模式由以下组件组成:

  • 抽象主题(Abstract Subject):抽象主题定义了代理对象和真实对象的共同接口。
  • 真实主题(Real Subject):真实主题是实际执行操作的对象。
  • 代理(Proxy):代理对象实现了抽象主题接口,并在执行操作时调用真实主题对象。代理对象可以在调用真实主题对象之前或之后添加额外的逻辑。

示例

<?php

// 抽象主题
interface Subject
{
    public function request();
}

// 真实主题
class RealSubject implements Subject
{
    public function request()
    {
        echo "真实主题处理请求。" . PHP_EOL;
    }
}

// 代理
class Proxy implements Subject
{
    private $realSubject;

    public function request()
    {
        if (!$this->realSubject) {
            $this->realSubject = new RealSubject();
        }

        $this->beforeRequest();
        $this->realSubject->request();
        $this->afterRequest();
    }

    private function beforeRequest()
    {
        echo "代理对象处理请求之前的操作。" . PHP_EOL;
    }

    private function afterRequest()
    {
        echo "代理对象处理请求之后的操作。" . PHP_EOL;
    }
}

// 客户端代码
$proxy = new Proxy();
$proxy->request();

在上面的示例中,我们给出了一个代理模式的示例实现。其中,抽象主题(Subject)定义了代理对象和真实对象的共同接口。真实主题(RealSubject)是实际执行操作的对象。代理(Proxy)对象实现了抽象主题接口,并在执行操作时调用真实主题对象。代理对象在调用真实主题对象之前和之后可以添加额外的逻辑。

通过使用代理模式,我们可以在不修改真实主题对象的情况下,对其进行访问控制、延迟实例化或添加额外的逻辑。代理模式提供了一种灵活的方式来管理对象的访问,并增强了系统的可维护性和扩展性。

概述

备忘录模式是一种行为型设计模式,它允许你捕获对象的内部状态并在需要时恢复它。通过将对象状态封装在备忘录对象中,备忘录模式可以在不破坏对象封装性的情况下实现状态的保存和恢复。

适用场景

备忘录模式适用于以下情况:

  • 当你需要保存和恢复对象的内部状态时,以便在后续时间点重新使用该状态。
  • 当直接访问对象的内部状态会暴露对象的实现细节,从而破坏封装性时。
  • 当你希望通过保存对象状态的历史记录来实现撤销/重做操作时。

结构

备忘录模式由以下组件组成:

  • 发起人(Originator):发起人是拥有内部状态的对象,它可以创建备忘录对象并从备忘录对象中恢复状态。
  • 备忘录(Memento):备忘录是存储发起人对象内部状态的对象。备忘录可以包含发起人的部分或全部状态信息。
  • 管理者(Caretaker):管理者负责存储和管理备忘录对象。它可以保存多个备忘录对象,并在需要时将其提供给发起人进行状态恢复。

示例

<?php

// 备忘录
class Memento
{
    private $state;

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

    public function getState()
    {
        return $this->state;
    }
}

// 发起人
class Originator
{
    private $state;

    public function setState($state)
    {
        $this->state = $state;
    }

    public function getState()
    {
        return $this->state;
    }

    public function save()
    {
        return new Memento($this->state);
    }

    public function restore(Memento $memento)
    {
        $this->state = $memento->getState();
    }
}

// 管理者
class Caretaker
{
    private $mementos = [];

    public function addMemento(Memento $memento)
    {
        $this->mementos[] = $memento;
    }

    public function getMemento($index)
    {
        return $this->mementos[$index];
    }
}

// 客户端代码
$originator = new Originator();
$caretaker = new Caretaker();

$originator->setState("State 1");
$caretaker->addMemento($originator->save());

$originator->setState("State 2");
$caretaker->addMemento($originator->save());

$originator->setState("State 3");

// 恢复到第一个备忘录
$originator->restore($caretaker->getMemento(0));
echo $originator->getState() . PHP_EOL; // 输出: State 1

// 恢复到第二个备忘录
$originator->restore($caretaker->getMemento(1));
echo $originator->getState() . PHP_EOL; // 输出: State 2

在上面的示例中,我们给出了一个备忘录模式的示例实现。其中,我们定义了备忘录(Memento)类,发起人(Originator)类和管理者(Caretaker)类。发起人类负责创建备忘录对象和恢复状态,而管理者类负责存储和管理备忘录对象。

概述

访问者模式是一种行为型设计模式,它允许你在不修改对象结构的前提下定义新的操作。通过将操作封装在访问者对象中,访问者模式可以让你在不同的对象上执行不同的操作。

适用场景

访问者模式适用于以下情况:

  • 当对象结构包含多个不同类型的对象,并且你希望对这些对象执行不同的操作时。
  • 当你希望在不修改对象类的前提下,新增一些新的操作或行为。
  • 当对象结构经常变化,但操作算法保持相对稳定时。

结构

访问者模式由以下组件组成:

  • 抽象元素(Abstract Element):抽象元素定义了接受访问者对象的接口。
  • 具体元素(Concrete Element):具体元素是抽象元素的实现,它提供了接受访问者对象的具体实现。
  • 抽象访问者(Abstract Visitor):抽象访问者定义了访问具体元素的接口。
  • 具体访问者(Concrete Visitor):具体访问者实现了抽象访问者定义的接口,并对具体元素执行相应的操作。
  • 对象结构(Object Structure):对象结构是一个容器,它存储了多个不同类型的元素,并提供了遍历元素的方法。

示例

<?php

// 抽象元素
interface Element
{
    public function accept(Visitor $visitor);
}

// 具体元素A
class ConcreteElementA implements Element
{
    public function accept(Visitor $visitor)
    {
        $visitor->visitElementA($this);
    }

    public function operationA()
    {
        echo "执行具体元素A的操作。" . PHP_EOL;
    }
}

// 具体元素B
class ConcreteElementB implements Element
{
    public function accept(Visitor $visitor)
    {
        $visitor->visitElementB($this);
    }

    public function operationB()
    {
        echo "执行具体元素B的操作。" . PHP_EOL;
    }
}

// 抽象访问者
interface Visitor
{
    public function visitElementA(ConcreteElementA $elementA);
    public function visitElementB(ConcreteElementB $elementB);
}

// 具体访问者
class ConcreteVisitor implements Visitor
{
    public function visitElementA(ConcreteElementA $elementA)
    {
        echo "访问者访问具体元素A,执行相应操作。" . PHP_EOL;
        $elementA->operationA();
    }

    public function visitElementB(ConcreteElementB $elementB)
    {
        echo "访问者访问具体元素B,执行相应操作。" . PHP_EOL;
        $elementB->operationB();
    }
}

// 对象结构
class ObjectStructure
{
    private $elements = [];

    public function attach(Element $element)
    {
        $this->elements[] = $element;
    }

    public function detach(Element $element)
    {
        $index = array_search($element, $this->elements, true);
        if ($index !== false) {
            unset($this->elements[$index]);
        }
    }

    public function accept(Visitor $visitor)
    {
        foreach ($this->elements as $element) {
            $element->accept($visitor);
        }
    }
}

// 客户端代码
$objectStructure = new ObjectStructure();

$elementA = new ConcreteElementA();
$elementB = new ConcreteElementB();

$objectStructure->attach($elementA);
$objectStructure->attach($elementB);

$visitor = new ConcreteVisitor();
$objectStructure->accept($visitor);

在上面的示例中,我们给出了一个访问者模式的示例实现。其中,我们定义了抽象元素(Element)接口和具体元素A(ConcreteElementA)和具体元素B(ConcreteElementB)的实现。接着,我们定义了抽象访问者(Visitor)接口和具体访问者(ConcreteVisitor)的实现。最后,我们创建了一个对象结构(ObjectStructure),并将具体元素添加到对象结构中。通过调用对象结构的accept方法,我们可以让访问者访问对象结构中的元素,并执行相应的操作。

通过使用访问者模式,我们可以在不修改元素类的情况下,定义新的操作或行为。访问者模式还可以帮助我们将相似的操作封装到一个访问者对象中,提高代码的复用性和可维护性。

karp

创建我自己的巨人