PHP设计模式详解:创建设计模式、结构设计模式及其应用场景
转载自:phpdesignpatterns [php中的设计模式] 1。简介[简介]

设计模式:提供了多种可重复使用的方法来解决我们在日常编程中经常遇到的问题。设计模式不一定是类库或第三方框架。它们更像是一个想法,并在系统中广泛使用。它们也显示为模式或模板,可用于在多种不同的情况下解决问题。设计模式可用于加速发展,并以简单的方式实施许多大型想法或设计。当然,尽管设计模式在开发中非常有用,但您必须避免在不适当的情况下滥用它们。
2。类别【类别】
根据目的和范围,设计模式可以分为五类。
根据目的,它分为:创建设计模式,结构设计模式和行为设计模式。
根据范围,它分为:类设计模式和对象设计模式。
1。根据目的,目前有23种常见的设计模式,可以根据使用目标将以下三类分为以下三个类别:
结构设计模式(7种类型):用于继承和接口的设计模式。结构设计模式用于新类的功能方法设计,减少了不必要的类定义并减少代码冗余。
行为模式(11种类型):用于方法实现和相应算法的设计模式,也是最复杂的设计模式。行为设计模式不仅用于定义类的功能行为,还用于不同类之间的协议和通信。
2。根据范围,将其分为:类设计模式和对象设计模式。
3。designPatternsprinciple [设计模式原理]设计模式的六个主要原理4。实现[设计模式实现]创建模式(创建设计模式)
1。Singleton(Singleton模式)
*/
final class Mysql
{
/**
*
* @var self[该属性用来保存实例]
*/
private static $instance;
/**
*
* @var mixed
*/
public $mix;
/**
* Return self instance[创建一个用来实例化对象的方法]
*
* @return self
*/
public static function getInstance()
{
if (! (self::$instance instanceof self)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* 构造函数为private,防止创建对象
*/
private function __construct()
{}
/**
* 防止对象被复制
*/
private function __clone()
{
trigger_error('Clone is not allowed !');
}
}
// @test
$firstMysql = Mysql::getInstance();
$secondMysql = Mysql::getInstance();
$firstMysql->mix = 'ityangs_one';
$secondMysql->mix = 'ityangs_two';
print_r($firstMysql->mix);
// 输出: ityangs_two
print_r($secondMysql->mix);
// 输出: ityangs_two
在许多情况下,有必要为系统中的多个类创建单顿构建方法,以便可以建立一种一般的抽象父厂方法:
*/
abstract class FactoryAbstract {
protected static $instances = array();
public static function getInstance() {
$className = self::getClassName();
if (!(self::$instances[$className] instanceof $className)) {
self::$instances[$className] = new $className();
}
return self::$instances[$className];
}
public static function removeInstance() {
$className = self::getClassName();
if (array_key_exists($className, self::$instances)) {
unset(self::$instances[$className]);
}
}
final protected static function getClassName() {
return get_called_class();
}
protected function __construct() { }
final protected function __clone() { }
}
abstract class Factory extends FactoryAbstract {
final public static function getInstance() {
return parent::getInstance();
}
final public static function removeInstance() {
parent::removeInstance();
}
}
// @test
class FirstProduct extends Factory {
public $a = [];
}
class SecondProduct extends FirstProduct {
}
FirstProduct::getInstance()->a[] = 1;
SecondProduct::getInstance()->a[] = 2;
FirstProduct::getInstance()->a[] = 11;
SecondProduct::getInstance()->a[] = 22;
print_r(FirstProduct::getInstance()->a);
// Array ( [0] => 1 [1] => 11 )
print_r(SecondProduct::getInstance()->a);
// Array ( [0] => 2 [1] => 22 )
2。工厂(工厂型号)
该工厂模式是另一种非常常用的模式,正如其名称所表明的那样:它确实是用于对象实例的生产工厂。从某种意义上说,工厂模式提供了一种共同的方法来帮助我们获取对象,而不必关心其特定的内部实施。
*/
interface SystemFactory
{
public function createSystem($type);
}
class MySystemFactory implements SystemFactory
{
// 实现工厂方法
public function createSystem($type)
{
switch ($type) {
case 'Mac':
return new MacSystem();
case 'Win':
return new WinSystem();
case 'Linux':
return new LinuxSystem();
}
}
}
class System{ /* ... */}
class WinSystem extends System{ /* ... */}
class MacSystem extends System{ /* ... */}
class LinuxSystem extends System{ /* ... */}
//创建我的系统工厂
$System_obj = new MySystemFactory();
//用我的系统工厂分别创建不同系统对象
var_dump($System_obj->createSystem('Mac'));//输出:object(MacSystem)#2 (0) { }
var_dump($System_obj->createSystem('Win'));//输出:object(WinSystem)#2 (0) { }
var_dump($System_obj->createSystem('Linux'));//输出:object(LinuxSystem)#2 (0) { }
3。摘要(抽象工厂模式)
在某些情况下,我们需要根据不同的选择逻辑提供不同的施工工厂,对于多个工厂,我们需要一个统一的抽象工厂:
*/
interface AbstractFactory {
public function CreateSystem();
public function CreateSoft();
}
class MacFactory implements AbstractFactory{
public function CreateSystem(){ return new MacSystem(); }
public function CreateSoft(){ return new MacSoft(); }
}
class WinFactory implements AbstractFactory{
public function CreateSystem(){ return new WinSystem(); }
public function CreateSoft(){ return new WinSoft(); }
}
//@test:创建工厂->用该工厂生产对应的对象
//创建MacFactory工厂
$MacFactory_obj = new MacFactory();
//用MacFactory工厂分别创建不同对象
var_dump($MacFactory_obj->CreateSystem());//输出:object(MacSystem)#2 (0) { }
var_dump($MacFactory_obj->CreateSoft());// 输出:object(MacSoft)#2 (0) { }
//创建WinFactory
$WinFactory_obj = new WinFactory();
//用WinFactory工厂分别创建不同对象
var_dump($WinFactory_obj->CreateSystem());//输出:object(WinSystem)#3 (0) { }
var_dump($WinFactory_obj->CreateSoft());//输出:object(WinSoft)#3 (0) { }
4。构建器(建筑商模式)
构建器模式主要在于创建一些复杂的对象。将复杂对象的构造与其表示形式分开,以便相同的构造过程可以为不同表示形式创建设计模式;
结构图:
_parts = array(); }
public function add($part) { return array_push($this->_parts, $part); }
}
/**
* 建造者抽象类
*
*/
abstract class Builder {
public abstract function buildPart1();
public abstract function buildPart2();
public abstract function getResult();
}
/**
*
* 具体建造者
* 实现其具体方法
*/
class ConcreteBuilder extends Builder {
private $_product;
public function __construct() { $this->_product = new Product(); }
public function buildPart1() { $this->_product->add("Part1"); }
public function buildPart2() { $this->_product->add("Part2"); }
public function getResult() { return $this->_product; }
}
/**
*
*导演者
*/
class Director {
public function __construct(Builder $builder) {
$builder->buildPart1();//导演指挥具体建造者生产产品
$builder->buildPart2();
}
}
// client
$buidler = new ConcreteBuilder();
$director = new Director($buidler);
$product = $buidler->getResult();
echo "";
var_dump($product);
echo "
“;/*输出:object(product)#2(1){[“ _parts”:“ product”:private] => array(2){[0] => string(5)“ part1” [1] = >字符串(5)“ part2”}} */?>
5。原型(原型模式)
有时,某些对象需要多次初始化。特别是如果初始化需要大量的时间和资源来预定位和存储这些对象,则将使用原型模式:
_name = $name; }
public function copy() { return clone $this;}
}
class Test {}
// client
$object1 = new ConcretePrototype(new Test());
var_dump($object1);//输出:object(ConcretePrototype)#1 (1) { ["_name":"ConcretePrototype":private]=> object(Test)#2 (0) { } }
$object2 = $object1->copy();
var_dump($object2);//输出:object(ConcretePrototype)#3 (1) { ["_name":"ConcretePrototype":private]=> object(Test)#2 (0) { } }
?>
结构模式6。适配器(适配器模式)
这种模式允许使用不同的接口重构类,并允许使用不同的调用方法调用:
_adaptee = $adaptee;
}
public function sampleMethod1() {
$this->_adaptee->sampleMethod1();
}
public function sampleMethod2() {
echo '————————';
}
}
$adapter = new Adapter(new Adaptee());
$adapter->sampleMethod1();//输出:++++++++
$adapter->sampleMethod2();//输出:————————
/**
* 第二种方式:类适配器
*/
interface Target2 {
public function sampleMethod1();
public function sampleMethod2();
}
class Adaptee2 { // 源角色
public function sampleMethod1() {echo '++++++++';}
}
class Adapter2 extends Adaptee2 implements Target2 { // 适配后角色
public function sampleMethod2() {echo '————————';}
}
$adapter = new Adapter2();
$adapter->sampleMethod1();//输出:++++++++
$adapter->sampleMethod2();//输出:————————
?>
7。桥(桥模式)
将抽象部分与其实施部分分开
桥梁和适配器模式之间的关系(上面已经说明了适配器模式):
桥梁是一种聚合关系,两者是相关但没有继承的。
适配器属于组合关系,并且适配器需要继承来源
聚合关系:一个对象可以包含b对象,但b对象不是对象的一部分
imp->operationImp();
}
}
class RefinedAbstraction extends Abstraction { // 修正抽象化角色, 扩展抽象化角色,改变和修正父类对抽象化的定义。
public function __construct(Implementor $imp) {
$this->imp = $imp;
}
public function operation() { $this->imp->operationImp(); }
}
// client
$abstraction = new RefinedAbstraction(new ConcreteImplementorA());
$abstraction->operation();//输出:A
$abstraction = new RefinedAbstraction(new ConcreteImplementorB());
$abstraction->operation();//输出:B
?>
8。复合(组成模式)
复合模式有时称为零件模式,该模式用于将对象组合到树结构中,以表示“部分局部”的层次关系。组合模式允许用户与单个对象和组合对象的使用一致。
常见用法方案:例如树菜单,文件夹菜单,部门组织结构图等。
_composites = array(); }
public function getComposite() { return $this; }
public function operation() {
foreach ($this->_composites as $composite) {
$composite->operation();
}
}
public function add(Component $component) { //聚集管理方法 添加一个子对象
$this->_composites[] = $component;
}
public function remove(Component $component) { // 聚集管理方法 删除一个子对象
foreach ($this->_composites as $key => $row) {
if ($component == $row) { unset($this->_composites[$key]); return TRUE; }
}
return FALSE;
}
public function getChild() { // 聚集管理方法 返回所有的子对象
return $this->_composites;
}
}
class Leaf implements Component {
private $_name;
public function __construct($name) { $this->_name = $name; }
public function operation() {}
public function getComposite() {return null;}
}
// client
$leaf1 = new Leaf('first');
$leaf2 = new Leaf('second');
$composite = new Composite();
$composite->add($leaf1);
$composite->add($leaf2);
$composite->operation();
$composite->remove($leaf2);
$composite->operation();
/**
*
*透明式合成模式
*/
interface Component { // 抽象组件角色
public function getComposite(); // 返回自己的实例
public function operation(); // 示例方法
public function add(Component $component); // 聚集管理方法,添加一个子对象
public function remove(Component $component); // 聚集管理方法 删除一个子对象
public function getChild(); // 聚集管理方法 返回所有的子对象
}
class Composite implements Component { // 树枝组件角色
private $_composites;
public function __construct() { $this->_composites = array(); }
public function getComposite() { return $this; }
public function operation() { // 示例方法,调用各个子对象的operation方法
foreach ($this->_composites as $composite) {
$composite->operation();
}
}
public function add(Component $component) { // 聚集管理方法 添加一个子对象
$this->_composites[] = $component;
}
public function remove(Component $component) { // 聚集管理方法 删除一个子对象
foreach ($this->_composites as $key => $row) {
if ($component == $row) { unset($this->_composites[$key]); return TRUE; }
}
return FALSE;
}
public function getChild() { // 聚集管理方法 返回所有的子对象
return $this->_composites;
}
}
class Leaf implements Component {
private $_name;
public function __construct($name) {$this->_name = $name;}
public function operation() {echo $this->_name."
";}
public function getComposite() { return null; }
public function add(Component $component) { return FALSE; }
public function remove(Component $component) { return FALSE; }
public function getChild() { return null; }
}
// client
$leaf1 = new Leaf('first');
$leaf2 = new Leaf('second');
$composite = new Composite();
$composite->add($leaf1);
$composite->add($leaf2);
$composite->operation();
$composite->remove($leaf2);
$composite->operation();
?>
9。装饰器(装饰器模式)
Decorator模式使我们可以在运行时根据不同方案在调用它之前和之后动态地将不同的行添加到对象中。
_component = $component;
}
public function operation() {
$this->_component->operation();
}
}
class ConcreteDecoratorA extends Decorator { // 具体装饰类A
public function __construct(Component $component) {
parent::__construct($component);
}
public function operation() {
parent::operation(); // 调用装饰类的操作
$this->addedOperationA(); // 新增加的操作
}
public function addedOperationA() {echo 'A加点酱油;';}
}
class ConcreteDecoratorB extends Decorator { // 具体装饰类B
public function __construct(Component $component) {
parent::__construct($component);
}
public function operation() {
parent::operation();
$this->addedOperationB();
}
public function addedOperationB() {echo "B加点辣椒;";}
}
class ConcreteComponent implements Component{ //具体组件类
public function operation() {}
}
// clients
$component = new ConcreteComponent();
$decoratorA = new ConcreteDecoratorA($component);
$decoratorB = new ConcreteDecoratorB($decoratorA);
$decoratorA->operation();//输出:A加点酱油;
echo '
--------
';
$decoratorB->operation();//输出:A加点酱油;B加点辣椒;
?>
10。立面(立面模式)
立面模式,也称为外观模式,用于为子系统中的一组接口提供一致的接口。外墙模式定义了高级接口,这使子系统更易于使用:引入立面角色后,用户只需要直接与立面角色进行交互,并且用户与子系统之间的复杂关系由立面角色,从而减少了系统。耦合
_camera1 = new Camera();
$this->_camera2 = new Camera();
$this->_light1 = new Light();
$this->_light2 = new Light();
$this->_light3 = new Light();
$this->_sensor = new Sensor();
$this->_alarm = new Alarm();
}
public function activate() {
$this->_camera1->turnOn();
$this->_camera2->turnOn();
$this->_light1->turnOn();
$this->_light2->turnOn();
$this->_light3->turnOn();
$this->_sensor->activate();
$this->_alarm->activate();
}
public function deactivate() {
$this->_camera1->turnOff();
$this->_camera2->turnOff();
$this->_light1->turnOff();
$this->_light2->turnOff();
$this->_light3->turnOff();
$this->_sensor->deactivate();
$this->_alarm->deactivate();
}
}
//client
$security = new SecurityFacade();
$security->activate();
?>
11。代理(代理模式)
代理模式(代理)为其他对象提供了控制对该对象的访问的代理。使用代理模式创建代理对象,允许代理对象控制对目标对象的访问(目标对象可以是远程对象,创建架空对象或需要安全控制的对象),并且可以添加一些附加功能而无需更改目标对象函数。
在某些情况下,客户端不需要或不能直接参考另一个对象,并且代理对象可以充当客户端和目标对象之间的中介,并且可以删除客户端无法通过代理对象或添加客户需要的额外服务。
一个经典的例子是网络代理。如果要访问Facebook或Twitter,您如何绕过GFW?找到一个代理
abstract class Subject { // 抽象主题角色
abstract public function action();
}
class RealSubject extends Subject { // 真实主题角色
public function __construct() {}
public function action() {}
}
class ProxySubject extends Subject { // 代理主题角色
private $_real_subject = NULL;
public function __construct() {}
public function action() {
$this->_beforeAction();
if (is_null($this->_real_subject)) {
$this->_real_subject = new RealSubject();
}
$this->_real_subject->action();
$this->_afterAction();
}
private function _beforeAction() {
echo '在action前,我想干点啥....';
}
private function _afterAction() {
echo '在action后,我还想干点啥....';
}
}
// client
$subject = new ProxySubject();
$subject->action();//输出:在action前,我想干点啥....在action后,我还想干点啥....
?>
12。轻巧(xiyuan模式)
使用共享技术有效支持大量细粒物体
武模式的变化是对象的存储开销
享受模式下的主要角色:
抽象的轻量级角色:此角色是所有具体的飞量级类的超类,并且为这些类别指定了需要实现的公共界面。那些需要出站状态的操作可以通过调用商业来传递为参数
混凝土轻巧的角色:实现轻量级接口,并撤回内部状态的存储空间(如果有)。混凝土轻巧对象必须可共享。它存储的状态必须是内部的
未共享ConcreteFly量的角色:并非所有的轻量级子类都需要共享。 Flyweigth使共享成为可能,但并不强迫共享
苍蝇权力角色:负责创建和管理武族角色。该角色必须确保系统可以正确共享享受对象
客户角色:此角色需要维持对所有元对象的参考。此角色需要单独存储所有实体对象的外部状态
享受元模式的优势:
轻量级模式可以显着减少内存中对象的数量
享受模式的缺点:
轻量级模式使系统更加复杂
轻量级模式将元对象的状态外部化,而阅读外部状态使运行时间稍长
适用的享受模式的方案:
当以下情况为真时,请使用轻巧模式:
1应用程序使用大量对象
2。大量对象的使用会导致大型存储空间。
3对象的大多数状态可以更改为外部状态
4如果删除对象的外部状态,则可以用相对较少的共享对象替换许多对象。
5个应用程序不依赖对象身份
resource = $resource_str;
}
public function operate(){
echo $this->resource."
";
}
}
class shareFlyWeight extends Resources{
private $resources = array();
public function get_resource($resource_str){
if(isset($this->resources[$resource_str])) {
return $this->resources[$resource_str];
}else {
return $this->resources[$resource_str] = $resource_str;
}
}
public function operate(){
foreach ($this->resources as $key => $resources) {
echo $key.":".$resources."
";
}
}
}
// client
$flyweight = new shareFlyWeight();
$flyweight->get_resource('a');
$flyweight->operate();
$flyweight->get_resource('b');
$flyweight->operate();
$flyweight->get_resource('c');
$flyweight->operate();
// 不共享的对象,单独调用
$uflyweight = new unShareFlyWeight('A');
$uflyweight->operate();
$uflyweight = new unShareFlyWeight('B');
$uflyweight->operate();
/* 输出:
a:a
a:a
b:b
a:a
b:b
c:c
A
B */
行为模式13。策略
策略模型主要是为了使客户类能够更好地使用某些算法而不知道其特定实现。
_strategy = $strategy;
}
public function handle_question() {
$this->_strategy->do_method();
}
}
// client
$strategyA = new ConcreteStrategyA();
$question = new Question($strategyA);
$question->handle_question();//输出do method A
$strategyB = new ConcreteStrategyB();
$question = new Question($strategyB);
$question->handle_question();//输出do method B
$strategyC = new ConcreteStrategyC();
$question = new Question($strategyC);
$question->handle_question();//输出do method C
?>
14。TemplateMethod(模板方法模式)
模板模式准备了一个抽象类,以具体方法和具体的构造形式实现了逻辑的一部分,然后声明了一些抽象方法来迫使子类实现其余逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而具有剩余逻辑的不同实现。首先开发一个顶级逻辑框架,然后将逻辑的详细信息留给要实现的特定子类。
primitiveOperation1();
$this->primitiveOperation2();
}
abstract protected function primitiveOperation1(); // 基本方法
abstract protected function primitiveOperation2();
}
class ConcreteClass extends AbstractClass { // 具体模板角色
protected function primitiveOperation1() {}
protected function primitiveOperation2(){}
}
$class = new ConcreteClass();
$class->templateMethod();
?>
15。观察者(观察者模式)
只要允许其他对象以某种方式注册为观察者,就可以将对象设置为可观察到的。每当观察对象变化时,信息就会发送给观察者。
_observers as $obs ){
$obs->onSendMsg( $this, $name );
}
}
public function addObserver( $observer ){
$this->_observers[]= $observer;
}
public function removeObserver($observer_name) {
foreach($this->_observers as $index => $observer) {
if ($observer->getName() === $observer_name) {
array_splice($this->_observers, $index, 1);
return;
}
}
}
}
class UserListLogger implements IObserver{
public function onSendMsg( $sender, $args ){
echo( "'$args' send to UserListLogger\n" );
}
public function getName(){
return 'UserListLogger';
}
}
class OtherObserver implements IObserver{
public function onSendMsg( $sender, $args ){
echo( "'$args' send to OtherObserver\n" );
}
public function getName(){
return 'OtherObserver';
}
}
$ul = new UserList();//被观察者
$ul->addObserver( new UserListLogger() );//增加观察者
$ul->addObserver( new OtherObserver() );//增加观察者
$ul->sendMsg( "Jack" );//发送消息到观察者
$ul->removeObserver('UserListLogger');//移除观察者
$ul->sendMsg("hello");//发送消息到观察者
/* 输出:'Jack' send to UserListLogger 'Jack' send to OtherObserver 'hello' send to OtherObserver */
?>
16。迭代器(迭代器模式)
迭代器模式,也称为光标模式。提供了一种方法,可以在不暴露对象的内部详细信息的情况下访问容器对象中的各个元素。
当您需要访问聚合的对象,而无论这些对象需要穿越什么,都应考虑使用迭代器模式。另外,当有多种遍历聚合的方法时,您可以考虑使用迭代图案。迭代器模式提供统一的接口,例如开始,下一个,是否结束以及当前用于遍历不同的聚合结构。
迭代器接口迭代器在PHP标准库(SPL)中提供。要实现迭代模式,就足以实现此接口。
_items = $data;
}
public function current() {
return current($this->_items);
}
public function next() {
next($this->_items);
}
public function key() {
return key($this->_items);
}
public function rewind() {
reset($this->_items);
}
public function valid() {
return ($this->current() !== FALSE);
}
}
// client
$data = array(1, 2, 3, 4, 5);
$sa = new sample($data);
foreach ($sa AS $key => $row) {
echo $key, ' ', $row, '
';
}
/* 输出:
0 1
1 2
2 3
3 4
4 5 */
//Yii FrameWork Demo
class CMapIterator implements Iterator {
/**
* @var array the data to be iterated through
*/
private $_d;
/**
* @var array list of keys in the map
*/
private $_keys;
/**
* @var mixed current key
*/
private $_key;
/**
* Constructor.
* @param array the data to be iterated through
*/
public function __construct(&$data) {
$this->_d=&$data;
$this->_keys=array_keys($data);
}
/**
* Rewinds internal array pointer.
* This method is required by the interface Iterator.
*/
public function rewind() {
$this->_key=reset($this->_keys);
}
/**
* Returns the key of the current array element.
* This method is required by the interface Iterator.
* @return mixed the key of the current array element
*/
public function key() {
return $this->_key;
}
/**
* Returns the current array element.
* This method is required by the interface Iterator.
* @return mixed the current array element
*/
public function current() {
return $this->_d[$this->_key];
}
/**
* Moves the internal pointer to the next array element.
* This method is required by the interface Iterator.
*/
public function next() {
$this->_key=next($this->_keys);
}
/**
* Returns whether there is an element at current position.
* This method is required by the interface Iterator.
* @return boolean
*/
public function valid() {
return $this->_key!==false;
}
}
$data = array('s1' => 11, 's2' => 22, 's3' => 33);
$it = new CMapIterator($data);
foreach ($it as $row) {
echo $row, '
';
}
/* 输出:
11
22
33 */
?>
17。责任链(责任链模型)
此模式有另一个名称:控制链模式。它主要由用于某些命令的一系列处理器组成。每个查询将通过处理器形成的责任链中传递。在每个十字路口,处理器确定是否需要对其进行响应和处理。每当处理器处理这些请求时,处理程序每次都会暂停。
next = $l;
return $this;
}
abstract public function operate(); // 操作方法
}
class ResponsibilityA extends Responsibility {
public function __construct() {}
public function operate(){
if (false == is_null($this->next)) {
$this->next->operate();
echo 'Res_A start'."
";
}
}
}
class ResponsibilityB extends Responsibility {
public function __construct() {}
public function operate(){
if (false == is_null($this->next)) {
$this->next->operate();
echo 'Res_B start';
}
}
}
$res_a = new ResponsibilityA();
$res_b = new ResponsibilityB();
$res_a->setNext($res_b);
$res_a->operate();//输出:Res_A start
?>
18。命令(命令模式)
命令模式:在软件系统中,“行为请求者”和“行为实施者”通常会呈现“紧密耦合”。但是,在某些情况下,例如“记录,撤销/重做,交易”和其他处理,这种无法抵抗变化的紧密耦合是不合适的。在这种情况下,您如何将“行为请求者”与“行为实施者”相结合?将一组行为抽象成对象,以实现两者之间的松散耦合。这是命令模式。
角色分析:
摘要命令:定义命令的接口并声明执行方法。
特定命令:命令接口实现对象是“虚拟”实现;它通常保留接收器并调用接收器的功能以完成命令执行的操作。
命令接收器:接收器,真正执行命令的对象。只要可以实现命令要求的相应功能,任何类都可以成为接收器。
控制器:要求命令对象执行请求,通常保存命令对象,并可以保存许多命令对象。这是客户端实际触发命令并要求命令执行相应操作的地方,这意味着它等于使用命令对象的输入。
_receiver = $receiver;
}
public function execute() {
$this->_receiver->action();
}
}
class Receiver { // 接收者角色
private $_name;
public function __construct($name) {
$this->_name = $name;
}
public function action() {
echo 'receive some cmd:'.$this->_name;
}
}
class Invoker { // 请求者角色
private $_command;
public function __construct(Command $command) {
$this->_command = $command;
}
public function action() {
$this->_command->execute();
}
}
$receiver = new Receiver('hello world');
$command = new ConcreteCommand($receiver);
$invoker = new Invoker($command);
$invoker->action();//输出:receive some cmd:hello world
?>
备忘模式也称为快照或令牌模式。备忘录模式的目的是捕获对象的内部状态,而无需破坏封装并将该状态保存在对象之外,以便当对象恢复其原始保存状态时可以在适当的情况下使用。
当我们编程时,我们通常需要保存对象的中间状态,并且在需要时,我们可以将其还原到该状态。例如,当我们使用Eclipse进行编程时,如果我们犯了写作错误(例如,意外删除了几行代码),我们希望在删除之前返回状态,以便我们可以使用CTRL+Z返回。目前,我们可以使用备忘模式来实现它。
uml:
在备忘录模式中涉及三个角色:纪念品角色,发起人角色和看守角色。
这三个角色的责任是:
发起者:记录当前时刻的内部状态,负责定义哪个状态属于备份范围,并负责创建和恢复备忘录数据。
备忘录:负责存储启动器对象的内部状态,并在需要时提供发起者所需的内部状态。
管理角色:管理备忘录,保存和提供备忘录。
_state = '';
}
public function createMemento() { // 创建备忘录
return new Memento($this->_state);
}
public function restoreMemento(Memento $memento) { // 将发起人恢复到备忘录对象记录的状态上
$this->_state = $memento->getState();
}
public function setState($state) { $this->_state = $state; }
public function getState() { return $this->_state; }
public function showState() {
echo $this->_state;echo "
";
}
}
class Memento { // 备忘录(Memento)角色
private $_state;
public function __construct($state) {
$this->setState($state);
}
public function getState() { return $this->_state; }
public function setState($state) { $this->_state = $state;}
}
class Caretaker { // 负责人(Caretaker)角色
private $_memento;
public function getMemento() { return $this->_memento; }
public function setMemento(Memento $memento) { $this->_memento = $memento; }
}
// client
/* 创建目标对象 */
$org = new Originator();
$org->setState('open');
$org->showState();
/* 创建备忘 */
$memento = $org->createMemento();
/* 通过Caretaker保存此备忘 */
$caretaker = new Caretaker();
$caretaker->setMemento($memento);
/* 改变目标对象的状态 */
$org->setState('close');
$org->showState();
$org->restoreMemento($memento);
$org->showState();
/* 改变目标对象的状态 */
$org->setState('close');
$org->showState();
/* 还原操作 */
$org->restoreMemento($caretaker->getMemento());
$org->showState();
/* 输出:
open
close
open
close
open */
?>
20。状态(状态模式)
状态模式允许在对象的内部状态发生变化时更改对象的行为,这看起来像已更改了类。状态模式主要解决了控制对象状态的条件表达式太复杂时的情况。将国家判断逻辑转移到代表不同状态的一系列类中可以简化复杂的判断逻辑。
UML类图:
角色:
上下文环境(工作):它定义了客户端程序所需的接口,并维护特定状态角色的实例,将与状态相关的操作委派给当前特定对象进行处理。
抽象状态:定义一个接口,以封装用法上下文的特定状态相关行为。
特定状态(AMSTATE):实现抽象状态定义的接口。
";
$context->setState(ConcreteStateB::getInstance());
}
}
class ConcreteStateB implements State { // 具体状态角色B
private static $_instance = null;
private function __construct() {}
public static function getInstance() {
if (is_null(self::$_instance)) {
self::$_instance = new ConcreteStateB();
}
return self::$_instance;
}
public function handle(Context $context) {
echo 'concrete_b'."
";
$context->setState(ConcreteStateA::getInstance());
}
}
class Context { // 环境角色
private $_state;
public function __construct() { // 默认为stateA
$this->_state = ConcreteStateA::getInstance();
}
public function setState(State $state) {
$this->_state = $state;
}
public function request() {
$this->_state->handle($this);
}
}
// client
$context = new Context();
$context->request();
$context->request();
$context->request();
$context->request();
/* 输出:
concrete_a
concrete_b
concrete_a
concrete_b */
?>
21。访客(访问者模式)
访问者模式是一种行为模式,其中访问者代表作用于对象结构中元素的操作。它可以定义在每个元素类上作用的新操作,而无需修改每个元素类,即动态添加特定的访客角色。
访问者模式使用双调度。首先将访问者传递到元素对象的接受方法中,然后将元素对象传递到访问者中,然后将访问者执行元素的相应方法。
主要角色
摘要访问者角色:为对象结构中的每个特定元素提供访问操作接口。操作接口的名称和参数标识要访问的特定元素角色。这使访问者可以通过元素角色的特定接口直接访问它。
混凝土访客角色(具体访问者):在抽象访问者角色接口中实现每个特定元素的角色声明的操作。
抽象节点角色:此接口定义了接受特定访问者的接受操作。
混凝土节点(节点)角色:在抽象节点角色中实现接受操作。
对象结构:这是使用访问者模式的必备角色。它必须具有以下特征:能够列举其元素;可以提供高级接口,以允许访客访问其元素;可以是复合(组合模式)或集合,例如列表或无序集合(在PHP中,我们使用数组,因为PHP中的数组最初是可以放置任何类型的数据的集合)
适用性
当有各种类型的聚合时,通常会使用访问者模式。在普通形式中,有必要确定每个元素属于哪种类型并执行相应的操作,从而创建一个冗长的条件转移语句。访问者模式可以更好地解决此问题。只需对每个元素均匀地调用元素 - >接受(Vistor)。
当访问的类结构相对稳定时,即不会随意添加访问者模式。访问者模式允许将新方法添加到访问的结构中。
_name = $name; }
public function getName() { return $this->_name; }
public function accept(Visitor $visitor) { // 接受访问者调用它针对该元素的新方法
$visitor->visitConcreteElementA($this);
}
}
class ConcreteElementB implements Element { // 具体元素B
private $_name;
public function __construct($name) { $this->_name = $name;}
public function getName() { return $this->_name; }
public function accept(Visitor $visitor) { // 接受访问者调用它针对该元素的新方法
$visitor->visitConcreteElementB($this);
}
}
class ObjectStructure { // 对象结构 即元素的集合
private $_collection;
public function __construct() { $this->_collection = array(); }
public function attach(Element $element) {
return array_push($this->_collection, $element);
}
public function detach(Element $element) {
$index = array_search($element, $this->_collection);
if ($index !== FALSE) {
unset($this->_collection[$index]);
}
return $index;
}
public function accept(Visitor $visitor) {
foreach ($this->_collection as $element) {
$element->accept($visitor);
}
}
}
// client
$elementA = new ConcreteElementA("ElementA");
$elementB = new ConcreteElementB("ElementB");
$elementA2 = new ConcreteElementB("ElementA2");
$visitor1 = new ConcreteVisitor1();
$visitor2 = new ConcreteVisitor2();
$os = new ObjectStructure();
$os->attach($elementA);
$os->attach($elementB);
$os->attach($elementA2);
$os->detach($elementA);
$os->accept($visitor1);
$os->accept($visitor2);
?>
22。调解员(调解人模式)
中间模式用于开发一个可以传输或介导修改这些对象的对象,而无需直接相互连接。通常,当处理具有相似属性并且需要保持同步的非耦合对象时,最好的方法是中介模式。它不是PHP中特别常见的设计模式。
_mediator = $mediator;
}
public function send($message) {
$this->_mediator->send($message,$this);
}
abstract public function notify($message);
}
class ConcreteMediator extends Mediator { // 具体中介者角色
private $_colleague1 = null;
private $_colleague2 = null;
public function send($message,$colleague) {
//echo $colleague->notify($message);
if($colleague == $this->_colleague1) {
$this->_colleague1->notify($message);
} else {
$this->_colleague2->notify($message);
}
}
public function set($colleague1,$colleague2) {
$this->_colleague1 = $colleague1;
$this->_colleague2 = $colleague2;
}
}
class Colleague1 extends Colleague { // 具体对象角色
public function notify($message) {
echo 'colleague1:'.$message."
";
}
}
class Colleague2 extends Colleague { // 具体对象角色
public function notify($message) {
echo 'colleague2:'.$message."
";
}
}
// client
$objMediator = new ConcreteMediator();
$objC1 = new Colleague1($objMediator);
$objC2 = new Colleague2($objMediator);
$objMediator->set($objC1,$objC2);
$objC1->send("to c2 from c1"); //输出:colleague1:to c2 from c1
$objC2->send("to c1 from c2"); //输出:colleague2:to c1 from c2
?>
23。解释器(解释器模式)
给定语言,定义语法的表示形式,并定义了使用表示形式来解释语言句子的解释器。
角色:
环境角色(PlayContent):定义解释规则的全局信息。
摘要解释器:定义部分解释具体实现,并封装了混凝土解释者实现的一些接口。
特定的解释器(MusicNote):实现抽象解释器的接口以执行特定的解释。
interpreter($temp);
echo "
";
}
}
}
//client
$obj = new Interpreter();
$obj->execute("123s45abc");
/* 输出:
一
二
三
S
四
五
A
B
C */
?>