在上一篇我们讲了结构型模式,结构型模式是讨论类和对象的结构的。总共有7种。而今天我们来介绍一下行为型模式。
一、什么是行为型模式?
行为型模式就是描述类和对象之间的通信和职责的。简而言之,就是类和对象扮演什么角色,还有怎么扮演这个角色的问题。
二、行为型模式的种类
大体上分为三个大类:常见模式、已知模式、深度模式
1、常见模式包括: 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、状态模式、职责链模式、策略模式
2、 已知模式包括:备忘录模式
3、深度模式包括:解释器模式 访问者模式
下面来介绍常见模式
Ø常见模式
1、模版方法模式(Template):
定义一个操作中的算法骨架,而将一些实现步骤延迟到子类当中实现。 就像一个豆浆机,不管放进去的是红豆还是黑豆,出来的都是豆浆。
好处:扩展性好,封装不变的代码,扩展可变的代码。
弊端:灵活性差,不能改变骨架部分。
应用场景:一类或一组具有共性的事物中。
代码实现
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
|
/** * 优才网公开课示例代码
*
* 模板方法模式 Template
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} class Request {
public $token = '' ;
public function __construct() {
$this ->token = '0c6b7289f5334ed2b697dd461eaf9812' ;
}
} class Response {
public function render( $content ) {
output(sprintf( 'response-render: %s' , $content ));
}
public function redirect( $uri ) {
output(sprintf( 'response-redirect: %s' , $uri ));
}
public function json( $data ) {
output(sprintf( 'response-data: %s' , json_encode( $data )));
}
} //父类,抽象类
abstract class Controller{
//封装了输入输出
protected $request ;
protected $response ;
//返回数据
protected $data = 'data' ;
public function __construct( $request , $response ){
$this ->request = $request ;
$this ->response = $response ;
}
//执行请求函数,定义总体算法(template method),final防止被复写(不允许子类改变总体算法)
public final function execute(){
$this ->before();
if ( $this ->valid()){
$this ->handleRequest();
}
$this ->after();
}
//定义hook method before,做一些具体请求的前置处理
//非abstract方法,子类可以选择覆盖或不覆盖,默认什么都不做
protected function before(){
}
//定义hook method valid,做请求的数据验证
//非abstract方法,子类可以选择覆盖或不覆盖,默认返回验证通过
protected function valid(){
return true;
}
//定义hook method handleRequest,处理请求
//定义为abstract方法,子类必须实现或也声明为抽象方法(由子类的子类负责实现)
abstract function handleRequest();
//定义hook method after,做一些请求的后置处理
//非abstract方法,子类可以选择覆盖或不覆盖,默认直接输出数据
protected function after(){
$this ->response->render( $this ->data);
}
} //子类1,实现父类开放的具体算法 class User extends Controller{
//覆盖before方法,实现具体算法,这是一个处理用户数据操作的控制器
//因此,我们选择在before里面判断用户是否已经登录了,这里简单判断下session数据
function before(){
if ( empty ( $_SESSION [ 'auth' ])){
//没登录就直接跳转了,不再执行后续的操作
$this ->response->redirect( "user/login.php" );
}
}
//覆盖valid方法,这里我们验证用户提交数据中有没有带验证token
function valid(){
if (isset( $this ->request->token)){
return true;
}
return false;
}
//覆盖handleRequest方法,必选,以为父类中声明了abstract了
function handleRequest(){
//做具体处理,一般根据参数执行不同的业务逻辑
}
//这个类我们选择不覆盖after方法,使用默认处理方式
} //子类2,实现父类开放的具体算法 class Post extends Controller{
//这个类我们选择不覆盖before方法,使用默认处理方式
//这个类我们选择不覆盖valid方法,使用默认处理方式
//覆盖handleRequest方法,必选,以为父类中声明了abstract了
function handleRequest(){
//做具体处理,一般根据参数执行不同的业务逻辑
$this ->data = array ( 'title' => 'ucai' );
}
//覆盖after方法,使用json格式输出数据
function after(){
$this ->response->json( $this ->data);
}
} class Client {
public static function test(){
$request = new Request();
$response = new Response();
//最终调用
$user = new User( $request , $response );
$user ->execute();
//最终调用
$post = new Post( $request , $response );
$post ->execute();
}
} Client::test(); |
2、命令模式(Command) :
行为请求者与行为实现者解耦。就像军队里的“敬礼”,不管是谁听到 这个命令都会做出标准的敬礼动作。
好处:便于添加和修改行为,便于聚合多个命令。
弊端:造成过多具体的命令类。
应用场景:对要操作的对象,进行的相同操作。
代码实现
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
|
/** * 优才网公开课示例代码
*
* 命令模式 Command
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} class Document {
private $name = '' ;
public function __construct( $name ) {
$this ->name = $name ;
}
public function showText() {
output(sprintf( "showText: %s" , $this ->name));
}
public function undo() {
output(sprintf( "undo-showText: %s" , $this ->name));
}
} class Graphics {
private $name = '' ;
public function __construct( $name ) {
$this ->name = $name ;
}
public function drawCircle() {
output(sprintf( "drawCircle: %s" , $this ->name));
}
public function undo() {
output(sprintf( "undo-drawCircle: %s" , $this ->name));
}
} class Client {
public static function test() {
$document = new Document( 'A' );
$graphics = new Graphics( 'B' );
$document ->showText();
$graphics ->drawCircle();
$document ->undo();
}
} Client::test(); <?php /** * 优才网公开课示例代码
*
* 命令模式 Command
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} interface Command {
public function execute();
public function undo();
} class Document implements Command {
private $name = '' ;
public function __construct( $name ) {
$this ->name = $name ;
}
public function execute() {
output(sprintf( "showText: %s" , $this ->name));
}
public function undo() {
output(sprintf( "undo-showText: %s" , $this ->name));
}
} class Graphics implements Command {
private $name = '' ;
public function __construct( $name ) {
$this ->name = $name ;
}
public function execute() {
output(sprintf( "drawCircle: %s" , $this ->name));
}
public function undo() {
output(sprintf( "undo-drawCircle: %s" , $this ->name));
}
} class Client {
public static function test() {
$array = array ();
array_push ( $array , new Document( 'A' ));
array_push ( $array , new Document( 'B' ));
array_push ( $array , new Graphics( 'C' ));
array_push ( $array , new Graphics( 'D' ));
foreach ( $array as $command ) {
$command ->execute();
}
$top = array_pop ( $array );
$top ->undo();
}
} Client::test(); <?php /** * 优才网公开课示例代码
*
* 命令模式 Command
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} interface Command {
public function execute();
public function undo();
} class Document {
private $name = '' ;
public function __construct( $name ) {
$this ->name = $name ;
}
public function showText() {
output(sprintf( "showText: %s" , $this ->name));
}
public function undo() {
output(sprintf( "undo-showText: %s" , $this ->name));
}
} class Graphics {
private $name = '' ;
public function __construct( $name ) {
$this ->name = $name ;
}
public function drawCircle() {
output(sprintf( "drawCircle: %s" , $this ->name));
}
public function undo() {
output(sprintf( "undo-drawCircle: %s" , $this ->name));
}
} class DocumentCommand implements Command {
private $obj = '' ;
public function __construct(Document $document ) {
$this ->obj = $document ;
}
public function execute() {
$this ->obj->showText();
}
public function undo() {
$this ->obj->undo();
}
} class GraphicsCommand implements Command {
private $obj = '' ;
public function __construct(Graphics $graphics ) {
$this ->obj = $graphics ;
}
public function execute() {
$this ->obj->drawCircle();
}
public function undo() {
$this ->obj->undo();
}
} class Client {
public static function test() {
$array = array ();
array_push ( $array , new DocumentCommand( new Document( 'A' )));
array_push ( $array , new DocumentCommand( new Document( 'B' )));
array_push ( $array , new GraphicsCommand( new Graphics( 'C' )));
array_push ( $array , new GraphicsCommand( new Graphics( 'D' )));
foreach ( $array as $command ) {
$command ->execute();
}
$top = array_pop ( $array );
$top ->undo();
}
} Client::test(); |
3、迭代器模式(Iterator):
访问聚合对象内容而不暴露内部结构。就像一个双色球彩票开奖一 样,每次都是摇出七个球,不能能摇不是七个球的中奖号码组合。
好处:以不同方式遍历一个集合。
弊端:每次遍历都是整个集合,不能单独取出元素。
应用场景:需要操作集合里的全部元素。
代码实现
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
|
/** * 优才网公开课示例代码
*
* 迭代器模式 Iterator
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} class RecordIterator implements Iterator{
private $position = 0;
//注意:被迭代对象属性是私有的
private $records = array ();
public function __construct(Array $records ) {
$this ->position = 0;
$this ->records = $records ;
}
function rewind () {
$this ->position = 0;
}
function current() {
return $this ->records[ $this ->position];
}
function key() {
return $this ->position;
}
function next() {
++ $this ->position;
}
function valid() {
return isset( $this ->records[ $this ->position]);
}
} class PostListPager {
protected $record = array ();
protected $total = 0;
protected $page = 0;
protected $size = 0;
public function __construct( $category , $page , $size ) {
$this ->page = $page ;
$this ->size = $size ;
// query db
$total = 28;
$this ->total = $total ;
$record = array (
0 => array ( 'id' => '1' ),
1 => array ( 'id' => '2' ),
2 => array ( 'id' => '3' ),
3 => array ( 'id' => '4' ),
);
//
$this ->record = $record ;
}
public function getIterator() {
return new RecordIterator( $this ->record);
}
public function getMaxPage() {
$max = intval ( $this ->total / $this ->size);
return $max ;
}
public function getPrevPage() {
return max( $this ->page - 1, 1);
}
public function getNextPage() {
return min( $this ->page + 1, $this ->getMaxPage());
}
} class Client {
public static function test(){
$pager = new PostListPager(1, 2, 4);
foreach ( $pager ->getIterator() as $key => $val ) {
output(sprintf( 'Key[%d],Val[%s]' , $key , json_encode( $val )));
}
output(sprintf( 'MaxPage[%d]' , $pager ->getMaxPage()));
output(sprintf( 'Prev[%d]' , $pager ->getPrevPage()));
output(sprintf( 'Next[%d]' , $pager ->getNextPage()));
$iterator = $pager ->getIterator();
while ( $iterator ->valid()){
print_r( $iterator ->current());
$iterator ->next();
}
$iterator -> rewind ();
}
} Client::test(); |
4、观察者模式(Observer):
又叫发布订阅模式,当一个主体对象发生改变时,依赖它的多个观察 者对象都得到通知并自动更新响应。就像报社一样,今天发布的消息只要 是看这份报纸的人看到的都是同样的内容。如果发布另一份报纸,也是一 样的。
好处:广播式通信,范围大一呼百应,便于操作一个组团,“公有制”。
弊端:不能单独操作组团里的个体,不能实行按需分配。
应用场景:操作多个对象,并操作相同。
代码实现
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
/** * 优才网公开课示例代码
*
* 观察者模式 Observer
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} //订单数据对象简单模拟,这个是实际需要被观察的对象(Subject),但是我们将其独立,然后 //通过构造方法传入到我们模式中的Subject中,这样使具体业务更加独立 class Order{
//订单号
private $id = '' ;
//用户ID
private $userId = '' ;
//用户名
private $userName = '' ;
//价格
private $price = '' ;
//下单时间
private $orderTime = '' ;
//订单数据填充简单模拟,实际应用中可能会读取用户表单输入并处理
public function __set( $name , $value ){
if (isset( $this -> $name )){
$this -> $name = $value ;
}
}
//获取订单属性
public function __get( $name ){
if (isset( $this -> $name )){
return $this -> $name ;
}
return "" ;
}
} //假设的DB类,便于测试,实际会存入真实数据库 class FakeDB{
public function save( $data ){
return true;
}
} class Client {
public static function test() {
//初始化一个订单数据
$order = new Order();
$order ->id = 1001;
$order ->userId = 9527;
$order ->userName = "God" ;
$order ->price = 20.0;
$order ->orderTime = time();
//向数据库保存订单
$db = new FakeDB();
$result = $db ->save( $order );
if ( $result ){
//实际应用可能会写到日志文件中,这里直接输出
output( "[OrderId:{$order->id}] [UseId:{$order->userId}] [Price:{$order->price}]" );
//实际应用会调用邮件发送服务如sendmail,这里直接输出
output( "Dear {$order->userName}: Your order {$order->id} was confirmed!" );
//实际应用会调用邮件发送服务如sendmail,这里直接输出
output( "Dear Manager: User {$order->userName}(ID:{$order->userId}) submitted a new order {$order->id}, please handle it ASAP!" );
}
}
} Client::test(); <?php /** * 优才网公开课示例代码
*
* 观察者模式 Observer
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} //订单数据对象简单模拟,这个是实际需要被观察的对象(Subject),但是我们将其独立,然后 //通过构造方法传入到我们模式中的Subject中,这样使具体业务更加独立 class Order{
//订单号
private $id = '' ;
//用户ID
private $userId = '' ;
//用户名
private $userName = '' ;
//价格
private $price = '' ;
//下单时间
private $orderTime = '' ;
//订单数据填充简单模拟,实际应用中可能会读取用户表单输入并处理
public function __set( $name , $value ){
if (isset( $this -> $name )){
$this -> $name = $value ;
}
}
//获取订单属性
public function __get( $name ){
if (isset( $this -> $name )){
return $this -> $name ;
}
return "" ;
}
} //被观察者, 负责维护观察者并在变化发生是通知观察者 class OrderSubject implements SplSubject {
private $observers ;
private $order ;
public function __construct(Order $order ) {
$this ->observers = new SplObjectStorage();
$this ->order = $order ;
}
//增加一个观察者
public function attach(SplObserver $observer ) {
$this ->observers->attach( $observer );
}
//移除一个观察者
public function detach(SplObserver $observer ) {
$this ->observers->detach( $observer );
}
//通知所有观察者
public function notify() {
foreach ( $this ->observers as $observer ) {
$observer ->update( $this );
}
}
//返回主体对象的具体实现,供观察者调用
public function getOrder() {
return $this ->order;
}
} //记录业务数据日志 (ActionLogObserver),实际可能还要抽象一层以处理不同的Action(业务操作),这里省略 class ActionLogObserver implements SplObserver{
public function update(SplSubject $subject ) {
$order = $subject ->getOrder();
//实际应用可能会写到日志文件中,这里直接输出
output( "[OrderId:{$order->id}] [UseId:{$order->userId}] [Price:{$order->price}]" );
}
} //给用户发送订单确认邮件 (UserMailObserver) class UserMailObserver implements SplObserver{
public function update(SplSubject $subject ) {
$order = $subject ->getOrder();
//实际应用会调用邮件发送服务如sendmail,这里直接输出
output( "Dear {$order->userName}: Your order {$order->id} was confirmed!" );
}
} //给管理人员发订单处理通知邮件 (AdminMailObserver) class AdminMailObserver implements SplObserver{
public function update(SplSubject $subject ) {
$order = $subject ->getOrder();
//实际应用会调用邮件发送服务如sendmail,这里直接输出
output( "Dear Manager: User {$order->userName}(ID:{$order->userId}) submitted a new order {$order->id}, please handle it ASAP!" );
}
} //假设的DB类,便于测试,实际会存入真实数据库 class FakeDB{
public function save( $data ){
return true;
}
} class Client {
public static function test() {
//初始化一个订单数据
$order = new Order();
$order ->id = 1001;
$order ->userId = 9527;
$order ->userName = "God" ;
$order ->price = 20.0;
$order ->orderTime = time();
//绑定观察者
$subject = new OrderSubject( $order );
$actionLogObserver = new ActionLogObserver();
$userMailObserver = new UserMailObserver();
$adminMailObserver = new AdminMailObserver();
$subject ->attach( $actionLogObserver );
$subject ->attach( $userMailObserver );
$subject ->attach( $adminMailObserver );
//向数据库保存订单
$db = new FakeDB();
$result = $db ->save( $order );
if ( $result ){
//通知观察者
$subject ->notify();
}
}
} Client::test(); |
5、中介者模式(Mediator):
用中介对象封装一系列的对象交互,中介使各对象不需要显式地相互引 用。
类似于邮局,邮寄者和收件者不用自己跑很远路,通过邮局就可以。
好处:简化了对象之间的关系,减少子类的生成。
弊端:中介对象可能变得非常复杂,系统难以维护。
应用场景:不需要显示地建立交互
代码实现
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
|
/** * 优才网公开课示例代码
*
* 中介者模式 Mediator
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} 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 ) {
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 ) {
output(sprintf( 'Colleague-1: %s' , $message ));
}
} class Colleague2 extends Colleague { // 具体对象角色
public function notify( $message ) {
output(sprintf( 'Colleague-2: %s' , $message ));
}
} class Client {
public static function test(){
// client
$objMediator = new ConcreteMediator();
$objC1 = new Colleague1( $objMediator );
$objC2 = new Colleague2( $objMediator );
$objMediator ->set( $objC1 , $objC2 );
$objC1 ->send( "to c2 from c1" );
$objC2 ->send( "to c1 from c2" );
}
} Client::test(); |
6、状态模式(State) :
对象在不同状态下表现出不同的行为。就像女朋友一样,高兴了牵你的 手,不高兴了遛狗。在两种状态下变现出不同的行为。
好处:避免if语句实用,方便增加新状态,封装了状态转换规则。
弊端:增加系统类和对象的数量。
应用场景:用于对象的不同功能的转换。
代码实现
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
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
|
/** * 优才网公开课示例代码
*
* 状态模式 State
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} abstract class ILift {
//电梯的四个状态
const OPENING_STATE = 1; //门敞状态
const CLOSING_STATE = 2; //门闭状态
const RUNNING_STATE = 3; //运行状态
const STOPPING_STATE = 4; //停止状态;
//设置电梯的状态
public abstract function setState( $state );
//首先电梯门开启动作
public abstract function open();
//电梯门有开启,那当然也就有关闭了
public abstract function close();
//电梯要能上能下,跑起来
public abstract function run();
//电梯还要能停下来
public abstract function stop();
} /** * 电梯的实现类
*/ class Lift extends ILift {
private $state ;
public function setState( $state ) {
$this ->state = $state ;
}
//电梯门关闭
public function close() {
//电梯在什么状态下才能关闭
switch ( $this ->state) {
case ILift::OPENING_STATE: //如果是则可以关门,同时修改电梯状态
$this ->setState(ILift::CLOSING_STATE);
break ;
case ILift::CLOSING_STATE: //如果电梯就是关门状态,则什么都不做
//do nothing;
return ;
break ;
case ILift::RUNNING_STATE: //如果是正在运行,门本来就是关闭的,也说明都不做
//do nothing;
return ;
break ;
case ILift::STOPPING_STATE: //如果是停止状态,本也是关闭的,什么也不做
//do nothing;
return ;
break ;
}
output( 'Lift colse' );
}
//电梯门开启
public function open() {
//电梯在什么状态才能开启
switch ( $this ->state){
case ILift::OPENING_STATE: //如果已经在门敞状态,则什么都不做
//do nothing;
return ;
break ;
case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以开启
$this ->setState(ILift::OPENING_STATE);
break ;
case ILift::RUNNING_STATE: //正在运行状态,则不能开门,什么都不做
//do nothing;
return ;
break ;
case ILift::STOPPING_STATE: //停止状态,淡然要开门了
$this ->setState(ILift::OPENING_STATE);
break ;
}
output( 'Lift open' );
}
///电梯开始跑起来
public function run() {
switch ( $this ->state){
case ILift::OPENING_STATE: //如果已经在门敞状态,则不你能运行,什么都不做
//do nothing;
return ;
break ;
case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以运行
$this ->setState(ILift::RUNNING_STATE);
break ;
case ILift::RUNNING_STATE: //正在运行状态,则什么都不做
//do nothing;
return ;
break ;
case ILift::STOPPING_STATE: //停止状态,可以运行
$this ->setState(ILift::RUNNING_STATE);
}
output( 'Lift run' );
}
//电梯停止
public function stop() {
switch ( $this ->state){
case ILift::OPENING_STATE: //如果已经在门敞状态,那肯定要先停下来的,什么都不做
//do nothing;
return ;
break ;
case ILift::CLOSING_STATE: //如是电梯时关闭状态,则当然可以停止了
$this ->setState(ILift::CLOSING_STATE);
break ;
case ILift::RUNNING_STATE: //正在运行状态,有运行当然那也就有停止了
$this ->setState(ILift::CLOSING_STATE);
break ;
case ILift::STOPPING_STATE: //停止状态,什么都不做
//do nothing;
return ;
break ;
}
output( 'Lift stop' );
}
} class Client {
public static function test() {
$lift = new Lift();
//电梯的初始条件应该是停止状态
$lift ->setState(ILift::STOPPING_STATE);
//首先是电梯门开启,人进去
$lift ->open();
//然后电梯门关闭
$lift ->close();
//再然后,电梯跑起来,向上或者向下
$lift ->run();
//最后到达目的地,电梯挺下来
$lift ->stop();
}
} Client::test(); <?php /** * 优才网公开课示例代码
*
* 状态模式 State
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} /** *
* 定义一个电梯的接口
*/ abstract class LiftState{
//定义一个环境角色,也就是封装状态的变换引起的功能变化
protected $_context ;
public function setContext(Context $context ){
$this ->_context = $context ;
}
//首先电梯门开启动作
public abstract function open();
//电梯门有开启,那当然也就有关闭了
public abstract function close();
//电梯要能上能下,跑起来
public abstract function run();
//电梯还要能停下来,停不下来那就扯淡了
public abstract function stop();
} /** * 环境类:定义客户感兴趣的接口。维护一个ConcreteState子类的实例,这个实例定义当前状态。
*/ class Context {
//定义出所有的电梯状态
static $openningState = null;
static $closeingState = null;
static $runningState = null;
static $stoppingState = null;
public function __construct() {
self:: $openningState = new OpenningState();
self:: $closeingState = new ClosingState();
self:: $runningState = new RunningState();
self:: $stoppingState = new StoppingState();
}
//定一个当前电梯状态
private $_liftState ;
public function getLiftState() {
return $this ->_liftState;
}
public function setLiftState( $liftState ) {
$this ->_liftState = $liftState ;
//把当前的环境通知到各个实现类中
$this ->_liftState->setContext( $this );
}
public function open(){
$this ->_liftState->open();
}
public function close(){
$this ->_liftState->close();
}
public function run(){
$this ->_liftState->run();
}
public function stop(){
$this ->_liftState->stop();
}
} /** * 在电梯门开启的状态下能做什么事情
*/ class OpenningState extends LiftState {
/**
* 开启当然可以关闭了,我就想测试一下电梯门开关功能
*
*/
public function close() {
//状态修改
$this ->_context->setLiftState(Context:: $closeingState );
//动作委托为CloseState来执行
$this ->_context->getLiftState()->close();
}
//打开电梯门
public function open() {
output( 'lift open...' );
}
//门开着电梯就想跑,这电梯,吓死你!
public function run() {
//do nothing;
}
//开门还不停止?
public function stop() {
//do nothing;
}
} /** * 电梯门关闭以后,电梯可以做哪些事情
*/ class ClosingState extends LiftState {
//电梯门关闭,这是关闭状态要实现的动作
public function close() {
output( 'lift close...' );
}
//电梯门关了再打开,逗你玩呢,那这个允许呀
public function open() {
$this ->_context->setLiftState(Context:: $openningState ); //置为门敞状态
$this ->_context->getLiftState()->open();
}
//电梯门关了就跑,这是再正常不过了
public function run() {
$this ->_context->setLiftState(Context:: $runningState ); //设置为运行状态;
$this ->_context->getLiftState()->run();
}
//电梯门关着,我就不按楼层
public function stop() {
$this ->_context->setLiftState(Context:: $stoppingState ); //设置为停止状态;
$this ->_context->getLiftState()->stop();
}
} /** * 电梯在运行状态下能做哪些动作
*/ class RunningState extends LiftState {
//电梯门关闭?这是肯定了
public function close() {
//do nothing
}
//运行的时候开电梯门?你疯了!电梯不会给你开的
public function open() {
//do nothing
}
//这是在运行状态下要实现的方法
public function run() {
output( 'lift run...' );
}
//这个事绝对是合理的,光运行不停止还有谁敢做这个电梯?!估计只有上帝了
public function stop() {
$this ->_context->setLiftState(Context:: $stoppingState ); //环境设置为停止状态;
$this ->_context->getLiftState()->stop();
}
} /** * 在停止状态下能做什么事情
*/ class StoppingState extends LiftState {
//停止状态关门?电梯门本来就是关着的!
public function close() {
//do nothing;
}
//停止状态,开门,那是要的!
public function open() {
$this ->_context->setLiftState(Context:: $openningState );
$this ->_context->getLiftState()->open();
}
//停止状态再跑起来,正常的很
public function run() {
$this ->_context->setLiftState(Context:: $runningState );
$this ->_context->getLiftState()->run();
}
//停止状态是怎么发生的呢?当然是停止方法执行了
public function stop() {
output( 'lift stop...' );
}
} /** * 模拟电梯的动作
*/ class Client {
public static function test() {
$context = new Context();
$context ->setLiftState( new ClosingState());
$context ->open();
$context ->close();
$context ->run();
$context ->stop();
}
} Client::test(); |
7、职责链模式 (Chainof Responsibility):
多个对象有机会处理请求,为请求发送者和接收者解耦。就像银行里 的取款机,不管那一台都可以取到钱。
好处:简单化对象隐藏链结构,便于添加新职责节点。
弊端:请求可能没有接受者,或者被多个接收者调用,性能降低。
应用场景:处理多种请求。
代码实现
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
|
/** * 优才网公开课示例代码
*
* 职责链模式 Chain of Responsibility
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} /** * 加入在公司里,如果你的请假时间小于0.5天,那么只需要向leader打声招呼就OK了。
如果0.5<=请假天数<=3天,需要先leader打声招呼,然后部门经理签字。 如果3<请假天数,需要先leader打声招呼,然后到部门经理签字,最后总经经理确认签字, 如果请假天数超过10天,是任何人都不能批准的。
*/
/** * 抽象处理者角色(Handler:Approver):定义一个处理请求的接口,和一个后继连接(可选)
*
*/
abstract class Handler
{ protected $_handler = null;
protected $_handlerName = null;
public function setSuccessor( $handler )
{
$this ->_handler = $handler ;
}
protected function _success( $request )
{
output(sprintf( "%s's request was passed" , $request ->getName()));
return true;
}
abstract function handleRequest( $request );
} /** * 具体处理者角色(ConcreteHandler:President):处理它所负责的请求,可以访问后继者,如果可以处理请求则处理,否则将该请求转给他的后继者。
*
*/
class ConcreteHandlerLeader extends Handler
{ function __construct( $handlerName ){
$this ->_handlerName = $handlerName ;
}
public function handleRequest( $request )
{
if ( $request ->getDay() < 0.5) {
output(sprintf( '%s was told' , $this ->_handlerName)); // 已经跟leader招呼了
return $this ->_success( $request );
}
if ( $this ->_handler instanceof Handler) {
return $this ->_handler->handleRequest( $request );
}
}
} /** * Manager
*
*/
class ConcreteHandlerManager extends Handler
{ function __construct( $handlerName ){
$this ->_handlerName = $handlerName ;
}
public function handleRequest( $request )
{
if (0.5 <= $request ->getDay() && $request ->getDay()<=3) {
output(sprintf( '%s signed' , $this ->_handlerName)); // 部门经理签字
return $this ->_success( $request );
}
if ( $this ->_handler instanceof Handler) {
return $this ->_handler->handleRequest( $request );
}
}
} class ConcreteHandlerGeneralManager extends Handler
{ function __construct( $handlerName ){
$this ->_handlerName = $handlerName ;
}
public function handleRequest( $request )
{
if (3 < $request ->getDay() && $request ->getDay() < 10){
output(sprintf( '%s signed' , $this ->_handlerName)); // 总经理签字
return $this ->_success( $request );
}
if ( $this ->_handler instanceof Handler) {
return $this ->_handler->handleRequest( $request );
} else {
output(sprintf( 'no one can approve request more than 10 days' ));
}
}
} /** * 请假申请
*
*/
class Request
{ private $_name ;
private $_day ;
private $_reason ;
function __construct( $name = '' , $day = 0, $reason = '' ){
$this ->_name = $name ;
$this ->_day = $day ;
$this ->_reason = $reason ;
}
public function setName( $name ){
$this ->_name = $name ;
}
public function getName(){
return $this ->_name;
}
public function setDay( $day ){
$this ->_day = $day ;
}
public function getDay(){
return $this ->_day ;
}
public function setReason( $reason ){
$this ->_reason = $reason ;
}
public function getReason( ){
return $this ->_reason;
}
} class Client {
public static function test(){
$leader = new ConcreteHandlerLeader( 'leader' );
$manager = new ConcreteHandlerManager( 'manager' );
$generalManager = new ConcreteHandlerGeneralManager( 'generalManager' );
//请求实例
$request = new Request( 'ucai' ,4, '休息' );
$leader ->setSuccessor( $manager );
$manager ->setSuccessor( $generalManager );
$result = $leader ->handleRequest( $request );
}
} Client::test(); |
8、策略模式(Strategy):
定义一系列算法,把每一个算法封装起来,并且使它们可相互替换。 就像篮球队里的球员,场上的和场下休息的。教练可以让场上的下来,也 可以让场下的上阵。
好处:定义可重用的一系列算法和行为,并且消除了if else语句。
弊端:调用端必须知道所有策略类。
应用场景:用于对象间的替换。
代码实现
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
|
/** * 优才网公开课示例代码
*
* 策略模式 Strategy
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} //策略基类接口 interface IStrategy {
public function OnTheWay();
} class WalkStrategy implements IStrategy {
public function OnTheWay() {
output( '在路上步行' );
}
} class RideBickStrategy implements IStrategy {
public function OnTheWay() {
output( '在路上骑自行车' );
}
} class CarStrategy implements IStrategy {
public function OnTheWay() {
output( '在路上开车' );
}
} //选择策略类Context class Context {
public function find( $strategy ) {
$strategy ->OnTheWay();
}
} class Client {
public static function test(){
$travel = new Context();
$travel ->find( new WalkStrategy());
$travel ->find( new RideBickStrategy());
$travel ->find( new CarStrategy());
}
} Client::test(); |
Ø已知模式
1、备忘录模式(Memento):
保存对象在一时刻的状态。亲,还记得“老师来了记得叫我一下”的 同桌的他吗?
好处:给用户提供了一种可以恢复状态的机制。
弊端:消耗资源。
应用场景:用于需要保存的数据。
代码实现
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
|
/** * 优才网公开课示例代码
*
* 备忘录模式 Memento
*
* @author 优才网全栈工程师教研组
* @see http://www.ucai.cn
*/
function output( $string ) {
echo $string . "n" ;
} 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() {
output( $this ->_state);
}
} 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 ; }
} class Client {
public static function test(){
$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( $caretaker ->getMemento());
$org ->showState();
}
} Client::test(); return ;
try {
$db ->beginTransaction();
$succ = $db -> exec ( $sql_1 );
if (! $succ ) {
throw new Exception( 'SQL 1 update failed' );
}
$succ = $db -> exec ( $sql_2 );
if (! $succ ) {
throw new Exception( 'SQL 2 update failed' );
}
$succ = $db -> exec ( $sql_3 );
if (! $succ ) {
throw new Exception( 'SQL 3 update failed' );
}
$db ->commit();
} catch (Exception $exp ) {
$db ->rollBack();
} |
Ø深度模式
1、解释器模式(Interpreter):
定义语言的文法,并建立一个解释器解释该语言中的句子。每个用过 字典的童鞋都懂滴。
好处:可扩展性比较好,灵活性大
弊端:可能难以维护复杂的文法
应用场景:用于成对或者一对多的需求中
2、访问者模式(Visitor):
封装某些用于作用于某种数据结构中各元素的操作,可以在不改变数 据结构的前提下定义作用于这些元素的新操作。如银行排号机。
好处:将相关的事物集中到一个访问者对象中。
弊端:增加新数据结构很困难。
应用场景:排队,排号。
三、总结
本篇介绍了行为型模式,行为模式涉及到算法和对象职责间的分配,行为类
模式采用继承机制在类间分派行为,TemplateMethod和Interpreter是类行为
模式。行为对象模式使用对象复合而不是继承,一些行为对象模式描述了一组相
互对等的对象如何相互协作以完成其中任何一个对象都单独无法完成的任务,如
Mediator在对象间引入一个mediator对象提供了松耦合所需的间接性;
Chain of Responsibility提供了更松的耦合,它通过一条候选对象链隐式的向一
个对象发松请求,可以运行时刻决定哪些候选者参与到链中;Observer定义并保
持了对象间的依赖关系;其它的行为对象模式常将行为封装封装在一个对象中,
并将请求指派给它,Strategy模式将算法封装在对象中,这样可以方面的改变和
指定一个对象所使用的算法;Command模式将请求封装在对象中,这样它就可
以作为参数来传递,已可以存储在历史列表中或以其它方式使用;State模式封
装一个对象的状态,使得当这个对象的状态对象变化时,该对象可改变它的行
为;Visitor模式封装分布于多个类之间的行为;而Iterator模式则抽象了访问和
遍历一个集合中对象的方式。
转载自: http://www.ucai.cn/blogdetail/7022?action=gt&mid=1
相关推荐
2. PHP设计模式的类型:PHP中常用的设计模式可以分为三大类,分别是创建型模式、结构型模式和行为型模式。创建型模式主要涉及对象实例化的过程,如单例模式、工厂模式、建造者模式等;结构型模式涉及如何组合类和...
3. 行为型模式:包括策略模式(Strategy)、模板方法模式(Template Method)、观察者模式(Observer)、迭代器模式(Iterator)、访问者模式(Visitor)、命令模式(Command)、备忘录模式(Memento)、状态模式...
《PHP设计模式》是一本探讨如何在PHP编程中应用设计模式的书籍。设计模式是软件工程领域中,解决常见问题的模板或策略。本书作者是美国的Aaron Saray,内容详尽地介绍了各种设计模式,旨在帮助PHP开发者构建出更加...
本压缩包“php设计模式代码”包含了作者亲笔编写的一些常见PHP设计模式的实现,下面将对这些设计模式进行详细的阐述。 1. **单例模式**:这种模式确保一个类只有一个实例,并提供一个全局访问点。在PHP中,单例模式...
设计模式通常分为三大类:创建型、结构型和行为型。在PHP中,以下是一些常见的设计模式及其应用: 1. **单例模式(Singleton)**:保证一个类只有一个实例,并提供一个全局访问点。在PHP中,单例模式常用于数据库...
3. 行为型模式: - 责任链模式:避免将请求的发送者和接收者耦合在一起,使得多个对象都有可能处理请求。 - 命令模式:将请求封装为一个对象,以便使用不同的请求、队列请求、或者记录请求日志。 - 解释器模式:...
PHP设计模式是将这些模式应用到PHP编程中的具体实现,可以帮助开发者编写更灵活、可维护和高效的代码。以下是对标题和描述中提及的一些设计模式的详细说明: 1. **解释器设计模式**:它允许我们创建一个简单的语言...
14. 状态模式:允许对象在其内部状态改变时改变其行为。它将条件分支逻辑封装到独立的类中,使代码更易于理解和维护。 15. 模板方法模式:定义一个操作中的算法骨架,而将一些步骤延迟到子类中。它使得子类可以不...
本资源包含了《PHP设计模式》一书中的实际代码示例,这些例程涵盖了多种设计模式,包括创建型、结构型和行为型模式。通过这些源码,开发者可以更直观地学习如何在实际项目中应用这些模式。 1. **创建型模式**: - ...
例如,工厂模式、单例模式、观察者模式等,都是在PHP开发中经常用到的设计模式。通过理解这些模式,开发者可以写出更灵活、可扩展的代码,并且能够更好地与其他开发者协作。 再者,“框架”章节会介绍一些流行的PHP...
**PHP设计模式详解** 在软件开发中,设计模式是一种经过时间考验、被广泛接受的解决方案模板,用于解决常见的设计问题。对于PHP开发者来说,理解并掌握设计模式是提升代码质量和可维护性的关键步骤。设计模式并非...
《PHP设计模式》一书由美国作者Aaron Saray撰写,主要针对PHP开发者,详细阐述了在实际编程过程中如何运用设计模式提升代码质量和可维护性。设计模式是软件工程中的最佳实践,它们是解决常见问题的经验总结,使得...
PHP设计模式主要分为三大类:创建型模式、结构型模式和行为型模式。 1. **创建型模式**: - 单例模式:确保一个类只有一个实例,并提供一个全局访问点。 - 工厂模式:提供一个接口来创建对象,但让子类决定实例化...
本文将深入探讨PHP中的面向对象和设计模式。 首先,我们来理解PHP的面向对象编程。在PHP 5及以上版本中,面向对象编程得到了全面支持,包括类、对象、继承、封装、多态等概念。类是对象的蓝图,定义了对象的属性...
设计模式分为三大类:创建型模式、结构型模式和行为型模式。每种模式都针对软件设计中的特定问题,提供了最佳实践的解决方案。 1. **创建型模式**: - **单例模式**:确保一个类只有一个实例,并提供一个全局访问...
在IT行业中,设计模式是软件开发中的重要概念,它们代表了在特定情境下解决常见问题的最佳实践。在PHP编程中,理解并应用设计模式能够帮助开发者编写出更灵活、可维护和可扩展的代码。本资源包含的"php23种完整设计...
设计模式通常分为三大类:创建型、结构型和行为型。创建型模式如工厂模式、抽象工厂模式、单例模式等,主要关注对象的创建过程,使得代码更加灵活,易于扩展。结构型模式如适配器模式、装饰器模式、代理模式等,关注...
3. 行为型模式:这类模式关注对象之间的交互和职责分配,包括责任链(Chain of Responsibility)、命令(Command)、解释器(Interpreter)、迭代器(Iterator)、备忘录(Memento)、观察者(Observer)、状态...
设计模式可以分为三大类:创建型模式、结构型模式和行为型模式。 创建型模式提供了创建对象的机制,同时又避免了暴露创建逻辑,并且提供了一种将创建逻辑和使用逻辑分离的清晰方式。例如: - 工厂模式(Factory ...