[PHP中的设计模式] 1. [简介]
设计模式:提供了多种可重用的方式来解决我们在日常编程中经常遇到的问题。设计模式不一定是类库或第三方框架。它们更多的是一种想法,并广泛应用于系统中。它们还显示为可用于解决许多不同场景中的问题的模式或模板。设计模式可用于加速开发并以简单的方式实现许多重要的想法或设计。当然,虽然设计模式在开发中非常有用,但是一定要避免在不合适的场景中误用它们。
2.【分类】
根据目的和范围,设计模式可以分为五类。
按照目的分为:创建型设计模式、结构型设计模式、行为型设计模式。
按范围分为:类设计模式、对象设计模式。
1、按照用途,目前常见的设计模式有23种,根据不同的使用目标可以分为以下三类:
结构设计模式 ( )(7 种):用于继承和接口的设计模式。采用结构化设计模式来设计新类的功能方法,减少不必要的类定义,减少代码冗余。
行为模式( )(11种):用于方法实现和相应算法的设计模式,也是最复杂的设计模式。行为设计模式不仅用于定义类的功能行为,还用于不同类之间的协议和通信。
2.按范围划分:类设计模式、对象设计模式
3.【设计模式原则】设计模式六大原则 4.【设计模式实现】(创建设计模式) 1.(单例模式)
/**
* Singleton class[单例模式]
* @author ITYangs
*/
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
很多情况下,需要为系统中的多个类创建单例构造方法。这样就可以建立一个通用的抽象父工厂方法:
/**
* Singleton class[单例模式:多个类创建单例的构造方式]
* @author ITYangs
*/
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.(工厂模式)
工厂模式是另一种非常常用的模式,顾名思义:它实际上是对象实例的生产工厂。从某种意义上说,工厂模式提供了一种通用的方法来帮助我们获取对象,而不需要关心它们的具体内部实现。
/**
* Factory class[工厂模式]
* @author ITYangs
*/
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.(抽象工厂模式)
某些情况下,我们需要根据不同的选择逻辑提供不同的构造工厂,而对于多个工厂,则需要一个统一的抽象工厂:
class System{}
class Soft{}
class MacSystem extends System{}
class MacSoft extends Soft{}
class WinSystem extends System{}
class WinSoft extends Soft{}
/**
* AbstractFactory class[抽象工厂模式]
* @author ITYangs
*/
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.(建造者模式)
建造者模式主要是创建一些复杂的对象。一种设计模式,将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示;
结构图:

/**
*
* 产品本身
*/
class Product {
private $_parts;
public function __construct() { $this->_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 "
";/*输出: ()#2 (1) {["":"":]=>array(2) {[0]=>(5) "Part1"[1]=>(5) "Part2 “}} */?>
5.(原型模式)
有时,某些对象需要多次初始化。特别是当初始化需要大量的时间和资源来预初始化和存储这些对象时,就会使用原型模式:
/**
*
* 原型接口
*
*/
interface Prototype { public function copy(); }
/**
* 具体实现
*
*/
class ConcretePrototype implements Prototype{
private $_name;
public function __construct($name) { $this->_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.(适配器模式)
该模式允许使用不同的接口重构类,并允许使用不同的调用方法进行调用:
/**
* 第一种方式:对象适配器
*/
interface Target {
public function sampleMethod1();
public function sampleMethod2();
}
class Adaptee {
public function sampleMethod1() {
echo '++++++++';
}
}
class Adapter implements Target {
private $_adaptee;
public function __construct(Adaptee $adaptee) {
$this->_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.(桥接模式)
将抽象部分与其实现部分分开,使它们能够独立。将抽象部分与其实现分开,即抽象类及其派生类用来实现自己的对象。
桥接与适配器模式的关系(适配器模式上面已经解释过):
是一种聚合关系,两者有关联但不继承。
适配器属于组合关系,适配器需要继承源
聚合关系:A对象可以包含B对象,但B对象不属于A对象
/**
*
*实现化角色, 给出实现化角色的接口,但不给出具体的实现。
*/
abstract class Implementor {
abstract public function operationImp();
}
class ConcreteImplementorA extends Implementor { // 具体化角色A
public function operationImp() {echo "A";}
}
class ConcreteImplementorB extends Implementor { // 具体化角色B
public function operationImp() {echo "B";}
}
/**
*
* 抽象化角色,抽象化给出的定义,并保存一个对实现化对象的引用
*/
abstract class Abstraction {
protected $imp; // 对实现化对象的引用
public function operation() {
$this->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.(合成模式)
组合模式( ),有时也称为部分-整体模式,用于将对象组合成树形结构,以表示“部分-整体”的层次关系。组合模式允许用户一致地使用单个对象和组合对象。
常见使用场景:如树形菜单、文件夹菜单、部门组织结构图等。
/**
*
*安全式合成模式
*/
interface Component {
public function getComposite(); //返回自己的实例
public function operation();
}
class Composite implements Component { // 树枝组件角色
private $_composites;
public function __construct() { $this->_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.(装饰器模式)
装饰器模式允许我们根据不同的运行时场景,在调用对象之前和之后动态添加不同的行。
interface Component {
public function operation();
}
abstract class Decorator implements Component{ // 装饰角色
protected $_component;
public function __construct(Component $component) {
$this->_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.(外观模式)
外观模式( mode),也称为外观模式,用于为子系统中的一组接口提供一致的接口。门面模式定义了一个高层接口,使子系统更易于使用:引入门面角色后,用户只需要直接与门面角色进行交互,用户与子系统之间的复杂关系由门面角色来实现。门面作用,从而降低系统成本。耦合度
class Camera {
public function turnOn() {}
public function turnOff() {}
public function rotate($degrees) {}
}
class Light {
public function turnOn() {}
public function turnOff() {}
public function changeBulb() {}
}
class Sensor {
public function activate() {}
public function deactivate() {}
public function trigger() {}
}
class Alarm {
public function activate() {}
public function deactivate() {}
public function ring() {}
public function stopRing() {}
}
class SecurityFacade {
private $_camera1, $_camera2;
private $_light1, $_light2, $_light3;
private $_sensor;
private $_alarm;
public function __construct() {
$this->_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.Proxy(代理模式)
代理模式(Proxy)为其他对象提供代理来控制对该对象的访问。使用代理模式创建代理对象,让代理对象控制对目标对象的访问(目标对象可以是远程对象、创建成本较高的对象、需要安全控制的对象),就可以添加一些额外内容而不更改目标对象。功能。
在某些情况下,客户端不想或不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介作用,可以通过代理对象删除客户端看不到的内容和服务或添加您的客户需要的额外服务。
一个典型的例子是网络代理。您想访问或如何绕过 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.(享元模式)
利用共享技术有效支持大量细粒度对象
享元模式改变的是对象的存储开销
享元模式中的主要角色:
()角色:该角色是所有具体的类的超类,指定了这些类需要实现的公共接口。那些需要出站状态的操作可以通过调用业务作为参数传入
()具体作用:实现接口,并为内部状态(如果有)拉回存储空间。对象必须是可共享的。它存储的状态必须是内部的
不共享的具体享元(八)角色:并非所有子类都需要共享。使共享成为可能,但并不强制共享
享元工厂()角色:负责创建和管理享元角色。该角色必须确保系统可以适当地共享享元对象
()角色:该角色需要维护所有对象的引用。该角色需要自己存储所有对象的外部状态
享元模式的优点:
模式可以大大减少内存中对象的数量
享元模式的缺点:
模式使系统变得更加复杂
该模式外化了享元对象的状态,读取外部状态使得运行时间稍长
享元模式适用场景:
当满足以下条件时使用该模式:
1 一个应用程序使用大量对象
2 完全由于使用了大量的对象,导致存储开销很大
3 对象的大部分状态都可以改变为外部状态
4 如果删除对象的外部状态,则可以用相对较少的共享对象替换许多对象组
5 应用程序不依赖于对象身份
abstract class Resources{
public $resource=null;
abstract public function operate();
}
class unShareFlyWeight extends Resources{
public function __construct($resource_str) {
$this->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.(策略模式)
策略模式主要是为了让客户端类能够在不知道其具体实现的情况下更好地使用某些算法。
interface Strategy { // 抽象策略角色,以接口实现
public function do_method(); // 算法接口
}
class ConcreteStrategyA implements Strategy { // 具体策略角色A
public function do_method() {
echo 'do method A';
}
}
class ConcreteStrategyB implements Strategy { // 具体策略角色B
public function do_method() {
echo 'do method B';
}
}
class ConcreteStrategyC implements Strategy { // 具体策略角色C
public function do_method() {
echo 'do method C';
}
}
class Question{ // 环境角色
private $_strategy;
public function __construct(Strategy $strategy) {
$this->_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.(模板方法模式)
模板模式准备一个抽象类,以具体方法和具体构造的形式实现部分逻辑,然后声明一些抽象方法来强制子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对其余逻辑有不同的实现。先开发一个顶层逻辑框架,把逻辑的细节留给具体的子类。
abstract class AbstractClass { // 抽象模板角色
public function templateMethod() { // 模板方法 调用基本方法组装顶层逻辑
$this->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.(观察者模式)
通过允许其他对象以某种方式注册为观察者,可以使对象变得可观察。每当被观察的对象发生变化时,就会向观察者发送一条消息。
interface IObserver{
function onSendMsg( $sender, $args );
function getName();
}
interface IObservable{
function addObserver( $observer );
}
class UserList implements IObservable{
private $_observers = array();
public function sendMsg( $name ){
foreach( $this->_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) 中提供了迭代器接口。要实现迭代器模式,只需实现此接口即可。
private $_items ;
public function __construct(&$data) {
$this->_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.(责任链模型)
这种模式还有一个名字:控制链模式。它主要由一系列处理某些命令的处理器组成。每个查询都将在处理器形成的职责链中传递。在每个交叉点,处理器都会确定是否需要响应并处理它们。当处理器可用于处理请求时,每个处理程序将暂停。
abstract class Responsibility { // 抽象责任角色
protected $next; // 下一个责任角色
public function setNext(Responsibility $l) {
$this->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.(命令模式)
命令模式:在软件系统中,“行为请求者”和“行为实现者”通常呈现“紧耦合”。但在某些情况下,比如“记录、撤消/重做、事务”等行为处理,这种无法抵抗变化的紧耦合是不合适的。那么,如何将“行为请求者”与“行为实现者”解耦呢?将一组行为抽象为对象,以实现它们之间的松耦合。这就是命令模式。
角色分析:
抽象命令:定义命令的接口并声明执行方法。
具体命令:命令接口实现对象是一个“虚拟”实现;它通常持有接收者并调用接收者的函数来完成命令要执行的操作。
命令接收者:接收者,实际执行命令的对象。任何类只要能够实现命令所需的相应功能,都可以成为接收者。
控制器:需要命令对象来执行请求,通常持有命令对象,并且可以持有很多命令对象。这里是客户端真正触发命令并要求命令执行相应操作的地方,相当于命令对象的入口。
interface Command { // 命令角色
public function execute(); // 执行方法
}
class ConcreteCommand implements Command { // 具体命令方法
private $_receiver;
public function __construct(Receiver $receiver) {
$this->_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
?>
19.(备忘录模式)
模式也称为快照模式()或Token模式。备忘录模式的目的是在不破坏封装性的情况下捕获对象的内部状态,并将此状态保存在对象外部,以便在适当的时候使用。将对象恢复到最初保存的状态。
我们在编程的时候,经常需要保存对象的中间状态,并在需要的时候恢复到这个状态。比如我们在编程的时候,如果写错了(比如不小心删掉了几行代码),想要回到删除之前的状态,就可以使用Ctrl+Z来返回。这时候我们就可以使用备忘录模式来实现这一点。
统一建模语言:

备忘录模式涉及到三个角色:memo()角色、发起人()角色、负责人()角色。
这三个角色的职责是:
发起者:记录当前时刻的内部状态,负责定义哪些状态属于备份范围,并负责创建和恢复备忘录数据。
备注:负责存储发起者对象的内部状态,并在需要时提供发起者所需的内部状态。
管理角色:管理备忘录、保存和提供备忘录。
class Originator { // 发起人(Originator)角色
private $_state;
public function __construct() {
$this->_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.State(状态模式)
状态模式允许在对象的内在状态更改时更改对象的行为,使对象看起来已更改其类。状态模式主要解决控制对象状态的条件表达式过于复杂的情况。通过将状态判断逻辑转移到一系列代表不同状态的类中,可以简化复杂的判断逻辑。
UML类图:

角色:
上下文(Work):定义了客户端程序所需的接口并维护特定状态角色的实例,并将状态相关操作委托给当前特定对象处理。
抽象状态(State):定义一个接口,使用上下文环境封装与特定状态相关的行为。
具体状态():实现抽象状态定义的接口。
interface State { // 抽象状态角色
public function handle(Context $context); // 方法示例
}
class ConcreteStateA implements State { // 具体状态角色A
private static $_instance = null;
private function __construct() {}
public static function getInstance() { // 静态工厂方法,返还此类的唯一实例
if (is_null(self::$_instance)) {
self::$_instance = new ConcreteStateA();
}
return self::$_instance;
}
public function handle(Context $context) {
echo 'concrete_a'."
";
$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.(访客模式)
访客模式是一种行为模式。访问者表示作用于对象结构中每个元素的操作。它可以定义作用于这些元素的新操作,而无需修改每个元素类,即动态添加特定的访问者角色。
访问者模式利用了双重调度的优势。首先将访问者传递给元素对象的方法,然后元素对象将自身传递给访问者,然后访问者执行元素对应的方法。
主角
抽象访问者角色():为对象结构()中的各个具体元素提供访问操作接口。操作接口的名称和参数标识了要访问的具体元素角色。这允许访问者通过该元素角色的特定界面直接访问它。
特定访问者角色():为每个特定元素角色实现抽象访问者角色接口中声明的操作。
抽象节点(Node)角色:该接口定义了接受特定访问者的操作。
具体节点(Node)角色:实现抽象节点角色中的操作。
对象结构角色():这是使用访问者模式所必需的角色。它必须具有以下特征:它可以枚举其元素;它可以提供高级接口以允许访问者访问其元素;它可以是复合(组合模式)或集合,例如列表或无序集合(在 PHP 中我们使用数组代替,因为 PHP 中的数组本质上是可以保存任何类型数据的集合)
适用性
访问者模式主要用于存在各种类型的聚合时。在普通形式中,需要判断每个元素属于什么类型,然后执行相应的操作,导致条件转移语句冗长。访客模式可以更好的解决这个问题。只需对每个元素统一调用 ->( ) 即可。
访问者模式多用于被访问的类的结构比较稳定的情况,即不会随便添加子类。访问者模式允许将新方法添加到访问的结构中。
interface Visitor { // 抽象访问者角色
public function visitConcreteElementA(ConcreteElementA $elementA);
public function visitConcreteElementB(concreteElementB $elementB);
}
interface Element { // 抽象节点角色
public function accept(Visitor $visitor);
}
class ConcreteVisitor1 implements Visitor { // 具体的访问者1
public function visitConcreteElementA(ConcreteElementA $elementA) {}
public function visitConcreteElementB(ConcreteElementB $elementB) {}
}
class ConcreteVisitor2 implements Visitor { // 具体的访问者2
public function visitConcreteElementA(ConcreteElementA $elementA) {}
public function visitConcreteElementB(ConcreteElementB $elementB) {}
}
class ConcreteElementA implements Element { // 具体元素A
private $_name;
public function __construct($name) { $this->_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 中不太常用的设计模式。
abstract class Mediator { // 中介者角色
abstract public function send($message,$colleague);
}
abstract class Colleague { // 抽象对象
private $_mediator = null;
public function __construct($mediator) {
$this->_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.(口译模式)
给定一种语言,定义其语法的表示,并定义一个使用该表示来解释该语言中的句子的解释器。
角色:
Role():定义解释规则的全局信息。
():定义了部分解释器的具体实现,并封装了具体解释器实现的一些接口。
具体解释器():实现抽象解释器的接口,进行具体的解释和执行。
class Expression { //抽象表示
function interpreter($str) {
return $str;
}
}
class ExpressionNum extends Expression { //表示数字
function interpreter($str) {
switch($str) {
case "0": return "零";
case "1": return "一";
case "2": return "二";
case "3": return "三";
case "4": return "四";
case "5": return "五";
case "6": return "六";
case "7": return "七";
case "8": return "八";
case "9": return "九";
}
}
}
class ExpressionCharater extends Expression { //表示字符
function interpreter($str) {
return strtoupper($str);
}
}
class Interpreter { //解释器
function execute($string) {
$expression = null;
for($i = 0;$i$string );$i++) {
$temp = $string[$i];
switch(true) {
case is_numeric($temp): $expression = new ExpressionNum(); break;
default: $expression = new ExpressionCharater();
}
echo $expression->interpreter($temp);
echo "
";
}
}
}
//client
$obj = new Interpreter();
$obj->execute("123s45abc");
/* 输出:
一
二
三
S
四
五
A
B
C */
?>
详细源码地址:
欢迎大家star,谢谢。
扫一扫在手机端查看
-
Tags : php工厂模式和容器
我们凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求,请立即点击咨询我们或拨打咨询热线: 13761152229,我们会详细为你一一解答你心中的疑难。


客服1