标签归档:读书总结

PHP设计模式笔记:使用PHP实现工厂模式

PHP设计模式笔记:使用PHP实现工厂模式

【意图】
定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method使用一个类的实例化延迟到其子类【GOF95】

【工厂模式结构图】

工厂方法模式

工厂方法模式

【工厂模式中主要角色】
抽象产品(Product)角色:具体产品对象共有的父类或接口
具体产品(Concrete Product)角色:实现抽象产品角色所定义的接口,并且工厂方法模式所创建的每一个对象都是某具体产品对象的实例
抽象工厂(Creator)角色:模式中任何创建对象的工厂类都要实现这个接口,它声明了工厂方法,该方法返回一个Product类型的对象。
Creator也可以定义一个工厂方法的缺省实现,它返回一个缺省的的ConcreteProduct对象
具体工厂(Concrete Creator)角色:实现抽象工厂接口,具体工厂角色与应用逻辑相关,由应用程序直接调用以创建产品对象。

【工厂模式的优点和缺点】
工厂模式的优点
工厂方法模式可以允许系统在不修改工厂角色的情况下引进新产品。

工厂模式的缺点
客户可能仅仅为了创建一个特定的ConcreteProduct对象,就不得不创建一个Creator子类

【工厂模式适用场景】
1、当一个类不知道它所必须创建的对象的类的时候
2、当一个类希望由它的子类来指定它所创建的对象的时候
3、当类将创建对象的职责委托给多个帮助子类的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候

【工厂模式与其它模式】
抽象工厂模式(abstract factory模式):Abstract Factory模式经常使用工厂方法来实现
Template Method模式: 工厂方法通常在Template Methods中被调用

【工厂模式PHP示例】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
 
<?php
/**
 * 工厂模式 2010-06-25 sz
 * @author 胖子 phppan.p#gmail.com  http://www.phppan.com
 * 哥学社成员(http://www.blog-brother.com/)
 * @package design pattern
 */
 
/**
 * 抽象工厂角色
 */
interface Creator {
    public function factoryMethod();
}
 
/**
 * 具体工厂角色A
 */
class ConcreteCreatorA implements Creator {
 
    /**
     * 工厂方法 返回具体 产品A
     * @return ConcreteProductA
     */
    public function factoryMethod() {
        return new ConcreteProductA();
    }
}
 
/**
 * 具体工厂角色B
 */
class ConcreteCreatorB implements Creator {
 
    /**
     * 工厂方法 返回具体 产品B
     * @return ConcreteProductB
     */
    public function factoryMethod() {
        return new ConcreteProductB();
    }
}
 
/**
 * 抽象产品角色
 */
interface Product {
    public function operation();                                                                                    
}
 
/**
 * 具体产品角色A
 */
class ConcreteProductA implements Product {
 
    /**
     * 接口方法实现 输出特定字符串
     */
    public function operation() {
        echo 'ConcreteProductA <br />';
    }
}
 
/**
 * 具体产品角色B
 */
class ConcreteProductB implements Product {
 
    /**
     * 接口方法实现 输出特定字符串
     */
    public function operation() {
        echo 'ConcreteProductB <br />';
    }
}
 
class Client {
 
    /**
     * Main program.
     */
    public static function main() {
        $creatorA = new ConcreteCreatorA();
        $productA = $creatorA->factoryMethod();
        $productA->operation();
 
        $creatorB = new ConcreteCreatorB();
        $productB = $creatorB->factoryMethod();
        $productB->operation();
    }
 
}
 
Client::main();
?>

【工厂方法模式与简单工厂模式】
工厂方法模式与简单工厂模式再结构上的不同不是很明显。工厂方法类的核心是一个抽象工厂类,而简单工厂模式把核心放在一个具体类上。
工厂方法模式之所以有一个别名叫多态性工厂模式是因为具体工厂类都有共同的接口,或者有共同的抽象父类。
当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了”开放-封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。
工厂方法模式退化后可以演变成简单工厂模式。

PHP设计模式笔记:使用PHP实现原型模式

PHP设计模式笔记:使用PHP实现原型模式

【意图】
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

【原型模式结构图】
Prototype

【原型模式中主要角色】
抽象原型(Prototype)角色:声明一个克隆自身的接口

具体原型(Concrete Prototype)角色:实现一个克隆自身的操作

【原型模式的优点和缺点】
Prototype模式优点:
1、可以在运行时刻增加和删除产品
2、可以改变值以指定新对象
3、可以改变结构以指定新对象
4、减少子类的构造
5、用类动态配置应用

Prototype模式的缺点:
Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。
而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。

【原型模式适用场景】
1、当一个系统应该独立于它的产品创建、构成和表示时,要使用Prototype模式
2、当要实例化的类是在运行时刻指定时,例如动态加载
3、为了避免创建一个与产品类层次平等的工厂类层次时;
4、当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些

【原型模式与其它模式】
抽象工厂模式(abstract factory模式):Abstract Factory模式与Prototype模式在某种方面是相互竞争的。但是也可以一起使用

【原型模式PHP示例】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
 
<?php
/**
 * 原型模式 2010-06-27 sz
 * @author phppan.p#gmail.com  http://www.phppan.com
 * 哥学社成员(http://www.blog-brother.com/)
 * @package design pattern
 */
 
/**
 * 抽象原型角色
 */
interface Prototype {
    public function copy();
}
 
/**
 * 具体原型角色
 */
class ConcretePrototype implements Prototype{
 
    private  $_name;
 
    public function __construct($name) {
        $this->_name = $name;
    }
 
    public function setName($name) {
        $this->_name = $name;
    }
 
    public function getName() {
        return $this->_name;
    }
 
    public function copy() {
       /* 深拷贝实现
        $serialize_obj = serialize($this);  //  序列化
        $clone_obj = unserialize($serialize_obj);   //  反序列化                                                     
        return $clone_obj;
        */
        return clone $this;     //  浅拷贝
    }
}
 
/**
 * 测试深拷贝用的引用类
 */
class Demo {
    public $array;
}
 
class Client {
 
     /**
     * Main program.
     */
    public static function main() {
 
        $demo = new Demo();
        $demo->array = array(1, 2);
        $object1 = new ConcretePrototype($demo);
        $object2 = $object1->copy();
 
        var_dump($object1->getName());
        echo '<br />';
        var_dump($object2->getName());
        echo '<br />';
 
        $demo->array = array(3, 4);
        var_dump($object1->getName());
        echo '<br />';
        var_dump($object2->getName());
        echo '<br />';
 
    }
 
}
 
Client::main();
?>

【浅拷贝与深拷贝】

浅拷贝
被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象。
即 浅拷贝只负责当前对象实例,对引用的对象不做拷贝。

深拷贝
被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量。那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原有那些被引用对象。
即 深拷贝把要拷贝的对象所引用的对象也都拷贝了一次,而这种对被引用到的对象拷贝叫做间接拷贝。
深拷贝要深入到多少层,是一个不确定的问题。
在决定以深拷贝的方式拷贝一个对象的时候,必须决定对间接拷贝的对象是采取浅拷贝还是深拷贝还是继续采用深拷贝。
因此,在采取深拷贝时,需要决定多深才算深。此外,在深拷贝的过程中,很可能会出现循环引用的问题。

利用序列化来做深拷贝
利用序列化来做深拷贝,把对象写到流里的过程是序列化(Serilization)过程,但在业界又将串行化这一过程形象的称为“冷冻”或“腌咸菜”过程;
而把对象从流中读出来的过程则叫做反序列化(Deserialization)过程,也称为“解冻”或“回鲜”过程。
在PHP中使用serialize和unserialize函数实现序列化和反序列化

在上面的代码中的注释就是一个先序列化再反序列化实现深拷贝的过程

PHP设计模式笔记:使用PHP实现门面模式

PHP设计模式笔记:使用PHP实现门面模式

【意图】
为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层次的接口,使得子系统更加容易使用【GOF95】
外部与子系统的通信是通过一个门面(Facade)对象进行。

【门面模式结构图】

门面模式

门面模式

【门面模式中主要角色】
门面(Facade)角色:
此角色将被客户端调用
知道哪些子系统负责处理请求
将用户的请求指派给适当的子系统

子系统(subsystem)角色:
实现子系统的功能
处理由Facade对象指派的任务
没有Facade的相关信息,可以被客户端直接调用
可以同时有一个或多个子系统,每个子系统都不是一个单独的类,而一个类的集合。每个子系统都可以被客户端直接调用,或者被门面角色调用。子系统并知道门面模式的存在,对于子系统而言,门面仅仅是另一个客户端。

【门面模式的优点】
1、它对客户屏蔽了子系统组件,因而减少了客户处理的对象的数目并使得子系统使用起来更加方便
2、实现了子系统与客户之间的松耦合关系
3、如果应用需要,它并不限制它们使用子系统类。因此可以在系统易用性与能用性之间加以选择

【门面模式适用场景】
1、为一些复杂的子系统提供一组接口
2、提高子系统的独立性
3、在层次化结构中,可以使用门面模式定义系统的每一层的接口

【门面模式与其它模式】
抽象工厂模式(abstract factory模式):Abstract Factory模式可以与Facade模式一起使用以提供一个接口,这一接口可用来以一种子系统独立的方式创建子系统对象。Abstract Factory模式也可以代替Facade模式隐藏那些与平台相关的类
调停者模式:Mediator模式与Facade模式的相似之处是,它抽象了一些已有类的功能。然而,Mediator目的是对同事之间的任意通讯进行抽象,通常集中不属于任何单个对象的功能。Mediator的同事对象知道中介者并与它通信,而不是直接与其他同类对象通信。相对而言,Facade模式仅对子系统对象的接口进行抽象,从而使它们更容易使用;它并定义不功能,子系统也不知道facade的存在
单例模式(singleton模式):一般来说,仅需要一个Facade对象,因此Facade对象通常属于Singleton对象。

【门面模式PHP示例】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
 
<?php
/**
 * 门面模式 2010-06-12 sz
 * 《Java与模式》上门面模式示例的PHP版本
 * @author phppan.p#gmail.com  http://www.phppan.com
 * 哥学社成员(http://www.blog-brother.com/)
 * @package design pattern
 */
 
class Camera {
 
    /**
     * 打开录像机
     */
    public function turnOn() {
        echo 'Turning on the camera.<br />';
    }
 
    /**
     * 关闭录像机
     */
    public function turnOff() {
        echo 'Turning off the camera.<br />';
    }
 
    /**
     * 转到录像机
     * @param <type> $degrees
     */
    public function rotate($degrees) {
        echo 'rotating the camera by ', $degrees, ' degrees.<br />';
    }
}
 
class Light {
 
    /**
     * 开灯
     */
    public function turnOn() {
        echo 'Turning on the light.<br />';
    }
 
    /**
     * 关灯
     */
    public function turnOff() {
        echo 'Turning off the light.<br />';
    }
 
    /**
     * 换灯泡
     */
    public function changeBulb() {
        echo 'changing the light-bulb.<br />';
    }
}
 
class Sensor {
 
    /**
     * 启动感应器
     */
    public function activate() {
        echo 'Activating the sensor.<br />';
    }
 
    /**
     * 关闭感应器
     */
    public function deactivate() {
        echo 'Deactivating the sensor.<br />';
    }
 
    /**
     * 触发感应器
     */
    public function trigger() {
        echo 'The sensor has been trigged.<br />';
    }
}
 
class Alarm {
 
    /**
     * 启动警报器
     */
    public function activate() {
        echo 'Activating the alarm.<br />';
    }
 
    /**
     * 关闭警报器
     */
    public function deactivate() {
        echo 'Deactivating the alarm.<br />';
    }
 
    /**
     * 拉响警报器
     */
    public function ring() {
        echo 'Ring the alarm.<br />';
    }
 
    /**
     * 停掉警报器
     */
    public function stopRing() {
        echo 'Stop the alarm.<br />';
    }
}
 
/**
 * 门面类
 */
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();
    }
}
 
 
/**
 * 客户端
 */
class Client {
 
    private static $_security;
     /**
     * Main program.
     */
    public static function main() {
        self::$_security = new SecurityFacade();
        self::$_security->activate();
    }
}
 
Client::main();
?>