月度归档:2010年05月

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

PHP设计模式笔记:使用PHP实现抽象工厂模式
抽象工厂模式(Abstact Factory)是一种常见的软件设计模式。该模式为一个产品族提供了统一的创建接口。当需要这个产品族的某一系列的时候,可以为此系列的产品族创建一个具体的工厂类。

【意图】
抽象工厂模式提供一个创建一系统相关或相互依赖对象的接口,而无需指定它们具体的类【GOF95】

【抽象工厂模式结构图】

抽象工厂模式

抽象工厂模式


【抽象工厂模式中主要角色】
抽象工厂(Abstract Factory)角色:它声明一个创建抽象产品对象的接口。通常以接口或抽象类实现,所有的具体工厂类必须实现这个接口或继承这个类。
具体工厂(Concrete Factory)角色:实现创建产品对象的操作。客户端直接调用这个角色创建产品的实例。这个角色包含有选择合适的产品对象的逻辑。通常使用具体类实现。
抽象产品(Abstract Product)角色:声明一类产品的接口。它是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。
具体产品(Concrete Product)角色:实现抽象产品角色所定义的接口,定义一个将被相应的具体工厂创建的产品对象。其内部包含了应用程序的业务逻辑。

【抽象工厂模式的优缺点】
抽象工厂模式的优点:
1、分离了具体的类
2、使增加或替换产品族变得容易
3、有利于产品的一致性

抽象工厂模式的缺点: 难以支持新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新各类的产品就需要扩展访工厂接口,从而导致AbstractFactory类及其所有子类的改变。
抽象工厂就是以一种倾斜的方式支持增加新的产品中,它为新产品族的增加提供了方便,而不能为新的产品等级结构的增加提供这样的方便。

【抽象工厂模式适用场景】
以下情况应当使用抽象工厂模式:
1、一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
2、这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
3、 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
4、系统提供一个产品类的库,所有的产品以同样的接口出现,从而使用客户端不依赖于实现
【Java与模式189页】

Abstract Factory模式的几个要点:
1、如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式。
2、“系列对象”指的是这项对象之间有相互依赖、或作用的关系。
3、Abstract Factory模式主要在于应对“新系列”的需求变动。缺点是难以应对
“新对象”的需求变动。这一点应该注意,就像前面说的,如果我们现在要在加入
其他系列的类,代码的改动会很大。
4、Abstract Factory模式经常和Factory Method模式共同组合来应对
“对象创建”的需求变化。

抽象工厂中的增加
1. 在产品等级结构的数目不变的情况下,增加新的产品族,就意味着在每一个产品等级结构中增加一个(或者多个)新的具体 (或者抽象和具体)产品角色。 由于工厂等级结构是与产品等级结构平行的登记机构,因此,当产品等级结构有所调整时, 需要将工厂等级结构做相应的调整。现在产品等级结构中出现了新的元素,因此, 需要向工厂等级结构中加入相应的新元素就可以了。 换言之,设计师只需要向系统中加入新的具体工厂类就可以了,没有必要修改已 有的工厂角色或者产品角色。因此,在系统中的产品族增加时,抽象工厂模式是支持“开-闭”原则的。

2. 在产品族的数目不变的情况下,增加新的产品等级结构。换言之,所有的产品等级结构 中的产品数目不会改变,但是现在多出一个与现有的产品等级结构平行的新的产品等级结构。 要做到这一点,就需要修改所有的工厂角色,给每一个工厂类都增加一个新的工厂方法, 而这显然是违背“开–闭”原则的。换言之,对于产品等级结构的增加,抽象工厂模式是不支持“开–闭”原则的。

综合起来,我们可以知道,在已有的抽象产品中添加其具体产品,支持“开—闭原则”, 然而在添加其抽象产品时,确不支持“开—闭”原则。抽象工厂模式以一种倾斜的 方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品等级 结构的增加提供这样的方便。

【抽象工厂模式与其它模式】
单例模式(singleton模式):具体工厂类可以设计成单例类,由于工厂通常有一个就可以,因此具体工厂子类一般都实现为一个Singleton。
工厂方法模式(factory method模式):抽象工厂创建产品的方法定义为工厂方法。
原型模式(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
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
 
<?php
/**
 * 抽象工厂模式 2010-05-28 sz
 * @author phppan.p#gmail.com  
 * http://www.phppan.com 哥学社成员(http://www.blog-brother.com/)
 * @package design pattern
 */
 
/**
 * 抽象工厂
 */
interface AbstractFactory {
    /**
     * 创建等级结构为A的产品的工厂方法
     */
    public function createProductA();
 
     /**
     * 创建等级结构为B的产品的工厂方法
     */
    public function createProductB();
 
}
 
/**
 * 具体工厂1
 */
class ConcreteFactory1 implements AbstractFactory{
 
    public function createProductA() {
        return new ProductA1();
    }
 
    public function createProductB() {
        return new ProductB1();
    }
}
 
 
/**
 * 具体工厂2
 */
class ConcreteFactory2 implements AbstractFactory{
 
    public function createProductA() {
        return new ProductA2();
    }
 
    public function createProductB() {
        return new ProductB2();
    }
}
 
/**
 * 抽象产品A
 */
interface AbstractProductA {
 
    /**
     * 取得产品名
     */
    public function getName();
}
 
/**
 * 抽象产品B
 */
interface AbstractProductB {
 
    /**
     * 取得产品名
     */
    public function getName();
}
 
/**
 * 具体产品A1
 */
class ProductA1 implements AbstractProductA {
    private $_name;
 
    public function __construct() {
        $this->_name = 'product A1';
    }
 
    public function getName() {
        return $this->_name;
    }
}
 
 
/**
 * 具体产品A2
 */
class ProductA2 implements AbstractProductA {
    private $_name;
 
    public function __construct() {
        $this->_name = 'product A2';
    }
 
    public function getName() {
        return $this->_name;
    }
}
 
 
/**
 * 具体产品B1
 */
class ProductB1 implements AbstractProductB {
    private $_name;
 
    public function __construct() {
        $this->_name = 'product B1';
    }
 
    public function getName() {
        return $this->_name;
    }
}
 
/**
 * 具体产品B2
 */
class ProductB2 implements AbstractProductB {
    private $_name;
 
    public function __construct() {
        $this->_name = 'product B2';
    }
 
    public function getName() {
        return $this->_name;
    }
}
 
 
/**
 * 客户端
 */
class Client {
 
     /**
     * Main program.
     */
    public static function main() {
        self::run(new ConcreteFactory1());
        self::run(new ConcreteFactory2());
    }
 
    /**
     * 调用工厂实例生成产品,输出产品名
     * @param   $factory    AbstractFactory     工厂实例
     */
    public static function run(AbstractFactory $factory) {
        $productA = $factory->createProductA();
        $productB = $factory->createProductB();
        echo $productA->getName(), '<br />';
        echo $productB->getName(), '<br />';
    }
 
}
 
Client::main();
?>

在Facebook中使用FBML对Fans显示内容,对非Fans隐藏内容

在Facebook中使用FBML对Fans显示内容,对非Fans隐藏内容

有一哥们跟我说要在Facebook中实现当有人访问某页面时隐藏,当点击like后可以看到隐藏的内容。
在查看了Facebook的FBML的帮助文档两个小时,测试过N多的标签后,终于看到了fb:visible-to-connection标签。
fb:visible-to-connection标签表现对于朋友或粉丝显示标签内的内容,此标签也可以搭配fb:else标签使用,对于非Fans显示fb:else标签内的内容。

当然首先我们需要使用:

1
<fb:fbml version=”1.1″>

请注意这里需要添加version属性。
然后在将你所要对Fans显示的内容放在:

1
<fb:visible-to-connection></fb:visible-to-connection>

之间,最后关闭fb:fbml标签

1
</fb:fbml>

下面是一个简单的示例:

1
2
3
4
5
6
<fb:fbml version="1.1">
<fb:visible-to-connection>
Weclome,Fans.
<fb:else>Non-fans.</fb:else>
</fb:visible-to-connection>
</fb:fbml>

如果不想让非Fans看到内容,将标签及标签内的内容移除即可。

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();
?>