标签归档:设计模式

PHP设计模式笔记:使用PHP实现建造者模式

PHP中的设计模式笔记:建造者模式

【Builder模式】
建造者模式可以让一个产品的内部表象和和产品的生产过程分离开,从而可以生成具有不同内部表象的产品。

【Builder模式结构图】

Builder模式简单示例图

Builder模式简单示例图


【Builder模式中主要角色】
抽象建造者(Builder)角色:定义一个抽象接口,规范产品各个组成成分的建造(即规范具体建造者的方法实现)。其中所规范的方法中必须包括建造方法和结果返回方法
具体建造者(ConcreteBuilder)角色:实现抽象建造者角色所定义的方法。具体建造者与业务逻辑关联性较大,应用程序最终会通过调用此角色中所实现的建造方法按照业务逻辑创建产品,在建造完成后通过结果返回方法返回建造的产品实例。一般在外部由客户或一个抽象工厂创建。
导演者(Director)角色:此角色的作用是调用具体的建造者角色建造产品。导演者与产品类没有直接关系,与产品类交谈的是具体抽象角色。
产品(Product)角色:在指导者的指导下由建造者所创建的那个复杂的对象
导演者角色与客户端直接打交道,它理解客户端的业务逻辑,将客户端创建产品的请求拆分成对产品组成部分的请求,然后调用具体产品角色执行建造操作。它分离了客户端与具体建造者。

【Builder模式的优缺点】
Builder模式的优点: 建造者模式可以很好的将一个对象的实现与相关的“业务”逻辑分离开来,从而可以在不改变事件逻辑的前提下,使增加(或改变)实现变得非常容易。
Builder模式的缺点: 建造者接口的修改会导致所有执行类的修改。

【Builder模式的使用场景与效果】
以下情况应当使用建造者模式:
1、 需要生成的产品对象有复杂的内部结构。
2、 需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。

使用建造者模式主要有以下效果:
1、 建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、 每一个Builder都相对独立,而与其它的Builder无关。
3、 模式所建造的最终产品更易于控制。
以上6点来自: http://www.cnblogs.com/lds85930/articles/643143.html

【Builder模式与其它模式】
抽象工厂模式(abstract factory模式):在抽象工厂模式中,每一次工厂对象被调用时都会返还一个完整的产品对象,而客户端可能会将这些产品组装成一个更大更复杂的产品,也可能不会。建造者模式则不同,它一点一点地建造出一个复杂的产品,而这个产品的组装过程发生在建造者内部。二者的区别在于是否有组装过程,组装过程发生的位置。这两个设计模式可以连起来用,客户端通过调用一个建造角色,间接调用另一个抽象工厂模式的工厂角色。工厂模式返还不同产品族的零件,而建造者模式则把它们组装起来。

策略模式(strategy模式):建造者模式在结构上很接近于策略模式,事实上建造者模式是策略模式的一种特殊情况。二者的区别在于用意不同。建造者模式作用于客户端一点一点的建造新的对象,而策略模式的目的是为算法提供抽象的接口。

建造者模式与模板方法模式:建造者模式在退化、失去导演者角色后,可以发展到模板方法模式(即将建造过程的算法实现放在建造角色中)。

建造者模式与合成模式:合成模式描述一个对象树的组成结构,而建造者模式则可以用来描述对象树的生成过程。
以上4点来自《Java与模式》

【Builder模式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
 
 
<?php
/**
 * 建造者模式 2010-05-23 sz
 * @author phppan.p#gmail.com
 * @package design pattern
 */
 
 
/**
 * 产品
 * 此处仅以一个产品类中的字符串演示产品
 */
class Product {                          
    /**
     * 产品的组成部分集合
     */
    private $_parts;
 
    public function __construct() {
        $this->_parts = array();
    }
 
    public function add($part) {
        return array_push($this->_parts, $part);
    }
 
    public function show() {
        echo "the product include:";
        array_map('printf', $this->_parts);
    }
}
 
/**
 * 抽象建造者 
 */
abstract class Builder {
 
    /**
     * 产品零件构造方法1
     */
    public abstract function buildPart1();
 
 
    /**
     * 产品零件构造方法2
     */
    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();
    }
}
 
 
 
class Client {
 
     /**
     * Main program.
     */
    public static function main() {
        $buidler = new ConcreteBuilder();
        $director = new Director($buidler);
        $product = $buidler->getResult();
        $product->show();
    }
 
}
 
Client::main();
?>

PHP设计模式笔记:使用PHP实现访问者模式

PHP中的设计模式笔记:访问者模式

【Visitor模式】
访问者模式表示一个作用于某对象结构中各元素的操作。它可以在不修改各元素类的前提下定义作用于这些元素的新操作,即动态的增加具体访问者角色。
访问者模式利用了双重分派。先将访问者传入元素对象的Accept方法中,然后元素对象再将自己传入访问者,之后访问者执行元素的相应方法。
访问者模式多用在聚集类型多样的情况下。在普通的形式下必须判断每个元素是属于什么类型然后进行相应的操作,从而诞生出冗长的条件转移语句。而访问者模式则可以比较好的解决这个问题。对每个元素统一调用$element->accept($vistor)即可。
访问者模式多用于被访问的类结构比较稳定的情况下,即不会随便添加子类。访问者模式允许被访问结构添加新的方法。
Visitor模式实际上是分离了对象结构中的元素和对这些元素进行操作的行为,从而使我们在根据对象结构中的元素进行方法调用的时候,不需要使用IF语句判断
也就是封装了操作
但是,如果增加新的元素节点,则会导致包括访问者接口及其子类的改变,这就会违反了面向对象中的开闭原则
当这种情况出现时,一般表示访问者模式已经可能不再适用了,或者说设计时就有问题了!

【Visitor模式结构图】

访问者模式简略图

访问者模式简略图



【Visitor模式中主要角色】
1)抽象访问者角色(Visitor):为该对象结构(ObjectStructure)中的每一个具体元素提供一个访问操作接口。该操作接口的名字和参数标识了 要访问的具体元素角色。这样访问者就可以通过该元素角色的特定接口直接访问它。
2)具体访问者角色(ConcreteVisitor):实现抽象访问者角色接口中针对各个具体元素角色声明的操作。
3)抽象节点(Node)角色:该接口定义一个accept操作接受具体的访问者。
4)具体节点(Node)角色:实现抽象节点角色中的accept操作。
5) 对象结构角色(ObjectStructure):这是使用访问者模式必备的角色。它要具备以下特征:能枚举它的元素;可以提供一个高层的接口以允许该访问者访问它的元素;可以是一个复合(组合模式)或是一个集合,如一个列表或一个无序集合(在PHP中我们使用数组代替,因为PHP中的数组本来就是一个可以放置任何类型数据的集合)

【Visitor模式的优缺点】
访问者模式有如下的优点:
1)访问者模式使得增加新的操作变得很容易。使用访问者模式可以在不用修改具体元素类的情况下增加新的操作。它主要是通过元素类的accept方法来接受一个新的visitor对象来实现的。如果一些操作依赖于一个复杂的结构对象的话,那么一般而言,增加新的操作会很复杂。而使用访问者模式,增加新的操作就意味着增加一个新的访问者类,因此,变得很容易。
2)访问者模式将有关的行为集中到一个访问者对象中,而不是分散到一个个的节点类中。
3)访问者模式可以跨过几个类的等级结构访问属于不同的等级结构的成员类。迭代子只能访问属于同一个类型等级结构的成员对象,而不能访问属于不同等级结构的对象。访问者模式可以做到这一点。
4)积累状态。每一个单独的访问者对象都集中了相关的行为,从而也就可以在访问的过程中将执行操作的状态积累在自己内部,而不是分散到很多的节点对象中。这是有益于系统维护的优点。

访问者模式有如下的缺点:
1)增加新的节点类变得很困难。每增加一个新的节点都意味着要在抽象访问者角色中增加一个新的抽象操作,并在每一个具体访问者类中增加相应的具体操作。
2)破坏封装。访问者模式要求访问者对象访问并调用每一个节点对象的操作,这隐含了一个对所有节点对象的要求:它们必须暴露一些自己的操作和内部状态。不然,访问者的访问就变得没有意义。由于访问者对象自己会积累访问操作所需的状态,从而使这些状态不再存储在节点对象中,这也是破坏封装的。

使用Visitor模式的前提: 对象群结构中(Collection) 中的对象类型很少改变。
在接口Visitor和Element中,确保Element很少变化,也就是说,确保不能频繁的添加新的Element元素类型加进来,可以变化的是访问者行为或操作,也就是Visitor的不同子类可以有多种,这样使用访问者模式最方便.
如果对象集合中的对象集合经常有变化, 那么不但Visitor实现要变化,ConcreteVisitor也要增加相应行为,GOF建议是,不如在这些对象类中直接逐个定义操作,无需使用访问者设计模式。

【Visitor模式与其它模式】
1、如果所浏览的结构对象是线性的,使用迭代模式而不是访问者模式也是可以的
2、访问者模式浏览合成模式的一些结构对象
以上两点来自《Java与模式》一书

【Visitor模式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
 
 
<?php
/**
 * 访问者模式 2010-05-13 sz
 * @author phppan.p#gmail.com
 * @package design pattern
 */
 
interface Visitor {
    public function visitConcreteElementA(ConcreteElementA $elementA);
    public function visitConcreteElementB(concreteElementB $elementB);
}
 
interface Element {
    public function accept(Visitor $visitor);
}
 
/**
 * 具体的访问者1
 */
class ConcreteVisitor1 implements Visitor {
    public function visitConcreteElementA(ConcreteElementA $elementA) {
        echo $elementA->getName() . " visitd by ConcerteVisitor1 <br />";
    }
 
    public function visitConcreteElementB(ConcreteElementB $elementB) {
        echo $elementB->getName() . " visited by ConcerteVisitor1 <br />";
    }
 
}
 
/**
 * 具体的访问者2
 */
class ConcreteVisitor2 implements Visitor {
    public function visitConcreteElementA(ConcreteElementA $elementA) {
        echo $elementA->getName() . " visitd by ConcerteVisitor2 <br />";
    }
 
    public function visitConcreteElementB(ConcreteElementB $elementB) {
        echo $elementB->getName() . " visited by ConcerteVisitor2 <br />";
    }
 
}
 
/**
 * 具体元素A
 */
class ConcreteElementA implements Element {
    private $_name;
 
    public function __construct($name) {
        $this->_name = $name;
    }
 
    public function getName() {
        return $this->_name;
    }
 
    /**
     * 接受访问者调用它针对该元素的新方法
     * @param Visitor $visitor
     */
    public function accept(Visitor $visitor) {
        $visitor->visitConcreteElementA($this);
    }
 
}
 
/**
 *  具体元素B
 */
class ConcreteElementB implements Element {
    private $_name;
 
    public function __construct($name) {
        $this->_name = $name;
    }
 
    public function getName() {
        return $this->_name;
    }
 
    /**
     * 接受访问者调用它针对该元素的新方法
     * @param Visitor $visitor
     */
    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);
        }
    }
}
 
class Client {
 
     /**
     * Main program.
     */
    public static function main() {
        $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);
    }
 
}
 
Client::main();
?>

【–EOF–】

妙解Hibernate 3.x——叩响面向对象思想之门 读书笔记

妙解Hibernate 3.x——叩响面向对象思想之门 读书笔记
在今年过生日的时候公司送了这本书给我,是部门老大挑的
找些时间看了下,由于在工作中并没有用到Hibernate,所有大部分内容没有看,
只看了前面的几章,当看到第三章,觉得仅第三章,这本书都值得一看(后面的章节由于用不到hibernate,只是简单过一遍)
第三章,看了不下三遍,觉得自己在某些地方还是看不懂,可能是对于面向对象的一些东西的理解还不够

使用继承、委托看待和拆解设计模式

将对象做虚,做软,不要被“变因”硬邦邦地绑住
—-封装变化

生成对象时,不直接new,才不会被具体对象绑死,此原则在学习面向对象中的创建模式有很好的指导作用
—-封装创建过程

模板方法与策略都将算法提取出来,只不过模板方法使用的是继承,策略使用的是委托
—-其实就这种模式,其本质应该是在其封装的变化的不同,模板方法是封装部分算法,而策略是封装整个算法
策略的重用性会高一些,只是需要付出一些额外的代价

回归最根本的面向对象思想:封装、继承、多态、委托

关于设计模式的学习:
1、接口、抽象类、具体对象是软件“软性”的指标之一,可按照实际需要的稳定性加以调整
2、研究模式三部曲:明确要解决的问题–>怎么解–>套用模式所带来的好处和副作用
3、从代码级看设计模式:
去掉new
去掉if/switch…case.
去掉重复的代码
4、开始接触一个新的设计模式,如果领导不到使用该模式的好处,不妨动手写一段程序,再来跟书中的实例进行比较
5、不时和自己的心灵对话—用自己的话来诠释模式,哪怕是简短的一句话,一个口诀,一个比喻
Builder 单一制程,不同风格
Sigleton just only one
Prototype 复制
Adapter 转换
Composite Tree
Decorator Dynamic composing behavior
Facade 简化
Proxy 本体/分身相互成就
Momento 借尸还魂
Strategy 替换多变的内部行为
6、不同的设计模式可能极其相似,搞不清是因为没有彻底掌握,这需要时间的积累
7、设计模式老是记不住,无法突破,那就放弃,过段时间再来温故知新
8、运用面向对象和设计模式,切忌矫枉过正,不要好处没得到,却被过度设计给弄复杂了

从Think in Data 到Think in Object

–EOF–