作者归档:admin

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–】

Oreilly.Developing.Large.Web.Applications.Mar.2010读后记录

Oreilly.Developing.Large.Web.Applications.Mar.2010读后记录

【概要】
作者偏向于使用动态语言将JS,CSS,HTML等代码全部封装在类中,从而实现整个应用的模块化
包括页面的模块化,数据的模块化,CSS的模块化,JS的模块化
读完全书…… 感觉有些纠结,不知道作者想干嘛,模块化?封装?应该是我水平不够!

【关键字】
模块化,封装,面向对象
内容,结构,表现,行为分离

【章节介绍与体会】
chapter1 The Tenets
总体介绍了这本书,差不多就是将整本书的每个章节进行了简单的说明
其中就模块化组件进行了介绍
原则一:由模块化组件构成的大型WEB应用是高可用的,可维护和可靠的
原则二:在大型WEB应用中,使用面向对象的JavaScript和服务器端脚本将推动应用的模块化,从而提高应用的可重用性,可维护性和可靠性
原则三:HTML是语义化,它本身是缺乏表现元素的, 但是它能以一种容易识别内容的形式插入到多种环境
HTML是一种对文本内容进行结构和意义(或者说“语义”)进行补充的方法
关于HTML的语义化的好处请猛击:http://www.vogim.com/teach/tutorial_show.aspx?id=395
原则四:CSS是信息架构的表现层,可以以模块化的形式在各种环境下复用
原则五:JavaScript是信息架构的行为层,可以以模块化和面向对象的形式在各种环境下复用
原则六:在用户接口与后端之间的数据交换可以通过一个清晰的数据接口定义来管理。页面定义一个单一的的点来加载和保存数据
原则七:以高可用性的模块组成的页面封装一切需要的东西(如HTML,CSS,JavaScript及其它),这可以使每个模块以独立的功能模块和聚合的单位用于各种环境的各个页面
原则八:Ajax是轻量和模块化的,并且在数据交换和更新之间保持一个清晰的隔离。在浏览器和服务器之间的数据交换可以通过一个定义清楚的接口来进行管理
原则九:大型HTML,JavaScript,CSS和PHP为建造一个大型的WEB应用提供了一个好的基础。他们还提升了网站测量和测试的环境
原则十:大型WEb应用的文件组织结构反映了这个应用的架构,其中包括明确划分每个文件的使用范围

chapter2 Object Orientation
这一章首先概述了面向对象以及为什么使用面向对象是一种比较好的方法,然后简单介绍了uml以及如何以面向对象的方式展现一个web页面,最后作者讲了PHP和Javascript中面向对象的一些基础知识
其中特别指出PHP是基于类的语言,而javascript是基于原型(或对象)的语言

chapter3 Large-Scale HTML
阐述了模块化对于一个好的信息架构的重要性,以及如何模块化HTML,其中推荐语义化的HTML
然后作者对于我们常用的HTML标签进行了区分,分出哪些是好的标签(例如:strong,div,body,ul,li等等),哪些是坏的(例如:font,i,hr,d等)
然后就id,class,name作了说明;
一个id在一个页面中只能出现一次
class是语义化的元素的一个集合,可以在一个页面出现多次
name属性用于表单提交数据到服务器
关于id和name的相同点和不同点请移步: http://www.phppan.com/2009/09/id-and-name-attribute-in-html/
然后就RDFa,XHTML及HTML5作了简单说明

chapter4 Large-Scale CSS
同样,在本章作者提出了模块化CSS的概念
一个好的WEB系统的表现层是通过CSS来实现的
首先说明了包含CSS的三个方法:链接,内联,嵌入,在嵌入CSS后,我们需要应用这些CSS,那么此时我们就会用到id(以#开头), class(以.号开头)以及使用后代(以空格隔开),元素,组(以逗号隔开)
然后介绍了CSS的应用范围,如模块级,页面级,其中就页面级范围,作者给了一个在body中添加id属性,使用CSS的后代应用方式控制显示的方法()
在本章的第二节,作者介绍了CSS中的定位技术,其中就盒子模型,文档流,相对定位,绝对定位和浮动,这对CSS的定位技术有一个不失简单的说明
第三节就层与容器分别作了一个简单的 示例,然后第四节就CSS重置及字体设置进行了简单说明,其中作者推荐使用YUI进行操作

chapter5 Large-Scale JavaScript
同CSS一样,作者提出了模块化Javascript的概念
首先在第一节作者对于包含Javascript进行了说明:它与CSS一样包含三种方法:链接,内联,嵌入,然后介绍了JS的命名空间和依据ID访问module
第二节介绍了DOM,以及常用的类库中的DOM
第三节介绍了事件驱动应用
第四节介绍了一些JS实现动画效果(动作,尺寸,颜色)

chapter6 Data Management
数据分为静态数据和动态数据,不同的数据的管理策略也不同
定义数据接口,所有的数据都从数据接口中获取,每个页面仅有一个点来获取数据
数据管理者是一个抽象和封装了特殊数据集的对象,并非每个模块都会有相应的数据管理者,也存在共用的数据管理者
在作者示例中可以看到数据管理者都会有相同的方法保存数据和获取数据,并且还提到了使用继承和委托的方式扩展数据
作者提到可用的数据源包括:SQL(数据库),XML
可以使用来自网络的数据,它通常包括XML格式或JSON格式
在本章的最后,作者介绍了cookie的数据管理,及表单的数据管理($_GET, $POST, $_REQUEST)

chapter7 Large-Scale PHP
整个章节都是围绕Page类来进行,从创建到使用
page类将包含一个页面的所有元素,将JS,CSS等文件也聚合在一起
包括数据的加载和保存,并依据模块创建内容
在这个类中包括JS管理,CSS管理,动态数据管理,页面内容管理,页面公用元素管理

层和容器是模块化的特殊形式

chapter8 Large-Scale Ajax
Ajax是旧技术的集合,是新瓶装旧酒的过程
通过 XMLHttpRequest对象向服务器发送异步请求,获取数据并在前台页面做局部的更新
Ajax在页面中通过Javascript与服务器建立连接,并更新页面。
Ajax支持基本的GET和POST方法
在服务器对于Ajax发送的请求处理需要注意三个方面:1、选择一种数据格式;2、使用服务器代理;3、模块化
MVC是基于发布/订阅模式(观察都模式)?

chapter9 Performance
作者推荐了High Performance Web Site这本书
缓存很重要,我们可以缓存CSS文件,JS文件,图片,甚至模块化的实体内容和页面
对于不是经常变化的数据和文件,缓存是一种不错的优化方案
给CSS文件和JS文件添加版本
合并CSS文件,合并JS文件,减少连接数
缓存模块化内容
缓存Ajax内容
使用Expires
压缩JS
减少重复
…………
(整章内容貌似都是拿yahoo军规说事)

chapter10 Application Architecture
整个应用程序的文件目录的组织

–EOF–