WEB开发笔记 www.chhua.com 每日练习 PHP设计模式——组合模式

以前我写过关于PHP组合模式的演示代码,感觉写的太过抽象,今天再重新写一下。
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
<span style="color: #000000;font-weight: bold"><?php</span>
 
abstract <span style="color: #000000;font-weight: bold">class</span> MenuComp <span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//写一个表示菜单和菜单选项之间相似性的抽象类</span>
	<span style="color: #000000;font-weight: bold">protected</span> <span style="color: #000088">$marked</span><span style="color: #339933">=</span><span style="color: #009900;font-weight: bold">FALSE</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//标识状态</span>
	<span style="color: #000000;font-weight: bold">protected</span> <span style="color: #000088">$label</span><span style="color: #339933">;</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> mark<span style="color: #009900">(</span><span style="color: #009900">)</span><span style="color: #009900">{</span><span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">marked</span><span style="color: #339933">=</span><span style="color: #009900;font-weight: bold">TRUE</span><span style="color: #339933">;</span><span style="color: #009900">}</span><span style="color: #666666;font-style: italic">//设置标记状态</span>
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> ismark<span style="color: #009900">(</span><span style="color: #009900">)</span><span style="color: #009900">{</span><span style="color: #b1b100">return</span> <span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">marked</span><span style="color: #339933">;</span><span style="color: #009900">}</span><span style="color: #666666;font-style: italic">//返回标记状态</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> setLabel<span style="color: #009900">(</span><span style="color: #000088">$label</span><span style="color: #009900">)</span><span style="color: #009900">{</span> <span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">label</span><span style="color: #339933">=</span><span style="color: #000088">$label</span><span style="color: #339933">;</span><span style="color: #009900">}</span><span style="color: #666666;font-style: italic">//设置标签</span>
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> getLabel<span style="color: #009900">(</span><span style="color: #009900">)</span><span style="color: #009900">{</span> <span style="color: #b1b100">return</span> <span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">label</span><span style="color: #339933">;</span><span style="color: #009900">}</span><span style="color: #666666;font-style: italic">//返回标签</span>
 
	abstract <span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> hasMenuOptionId<span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//抽象方法用来标识ID</span>
	abstract <span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> MarkPathToMenuOption<span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//抽象方法用来标识菜单路径</span>
<span style="color: #009900">}</span>
 
<span style="color: #000000;font-weight: bold">class</span> menu <span style="color: #000000;font-weight: bold">extends</span> MenuComp<span style="color: #009900">{</span>
	<span style="color: #000000;font-weight: bold">protected</span> <span style="color: #000088">$marked</span><span style="color: #339933">=</span><span style="color: #009900;font-weight: bold">false</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//标记状态</span>
	<span style="color: #000000;font-weight: bold">protected</span> <span style="color: #000088">$label</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//菜单标签</span>
	<span style="color: #000000;font-weight: bold">private</span> <span style="color: #000088">$children</span><span style="color: #339933">=</span><a rel="noopener noreferrer nofollow" href="http://www.php.net/array" rel="noopener noreferrer nofollow" target="_blank"><span style="color: #990000">array</span></a><span style="color: #009900">(</span><span style="color: #009900">)</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//子菜单或子菜单选项数组</span>
	<span style="color: #000000;font-weight: bold">private</span> <span style="color: #000088">$id</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//菜单ID</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> __construct<span style="color: #009900">(</span><span style="color: #000088">$label</span><span style="color: #339933">,</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//构造函数用来设置标签和ID</span>
		<span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">label</span><span style="color: #339933">=</span><span style="color: #000088">$label</span><span style="color: #339933">;</span>
		<span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">id</span><span style="color: #339933">=</span><span style="color: #000088">$id</span><span style="color: #339933">;</span>
	<span style="color: #009900">}</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> add<span style="color: #009900">(</span><span style="color: #000088">$child</span><span style="color: #009900">)</span><span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//添加菜单</span>
		<span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">children</span><span style="color: #009900">[</span><span style="color: #009900">]</span><span style="color: #339933">=</span><span style="color: #000088">$child</span><span style="color: #339933">;</span>
	<span style="color: #009900">}</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> hasMenuOptionId<span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//用迭代方式询问所有子对象上是否有对应ID的菜单选项</span>
		<span style="color: #b1b100">foreach</span> <span style="color: #009900">(</span><span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">children</span> <span style="color: #b1b100">as</span> <span style="color: #000088">$child</span><span style="color: #009900">)</span><span style="color: #009900">{</span>
			<span style="color: #b1b100">if</span> <span style="color: #009900">(</span><span style="color: #000088">$child</span><span style="color: #339933">-></span><span style="color: #004000">hasMenuOptionID</span><span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">)</span> <span style="color: #b1b100">return</span> <span style="color: #009900;font-weight: bold">TRUE</span><span style="color: #339933">;</span>
		<span style="color: #009900">}</span>
		<span style="color: #b1b100">return</span> <span style="color: #009900;font-weight: bold">FALSE</span><span style="color: #339933">;</span>
	<span style="color: #009900">}</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> MarkPathToMenuOption<span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//用迭代方式标记路径</span>
		<span style="color: #b1b100">if</span> <span style="color: #009900">(</span><span style="color: #339933">!</span><span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">hasMenuOptionId</span><span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">)</span> <span style="color: #b1b100">return</span> <span style="color: #009900;font-weight: bold">FALSE</span><span style="color: #339933">;</span>
		<span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">mark</span><span style="color: #009900">(</span><span style="color: #009900">)</span><span style="color: #339933">;</span>
		<span style="color: #b1b100">foreach</span> <span style="color: #009900">(</span><span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">children</span> <span style="color: #b1b100">as</span> <span style="color: #000088">$child</span><span style="color: #009900">)</span><span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//用迭代方式</span>
			<span style="color: #000088">$child</span><span style="color: #339933">-></span><span style="color: #004000">MarpathToMenuOption</span><span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #339933">;</span>
		<span style="color: #009900">}</span>
	<span style="color: #009900">}</span>
<span style="color: #009900">}</span>
 
<span style="color: #000000;font-weight: bold">class</span> menuOption <span style="color: #000000;font-weight: bold">extends</span> MenuComp <span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//菜单选项类</span>
	<span style="color: #000000;font-weight: bold">protected</span> <span style="color: #000088">$marked</span><span style="color: #339933">=</span><span style="color: #009900;font-weight: bold">false</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//标记状态</span>
	<span style="color: #000000;font-weight: bold">protected</span> <span style="color: #000088">$label</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//菜单标签例如:www.chhua.com</span>
	<span style="color: #000000;font-weight: bold">private</span> <span style="color: #000088">$id</span><span style="color: #339933">;</span><span style="color: #666666;font-style: italic">//菜单ID</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> __construct<span style="color: #009900">(</span><span style="color: #000088">$label</span><span style="color: #339933">,</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">{</span><span style="color: #666666;font-style: italic">//构造函数用来设置标签和ID</span>
		<span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">label</span><span style="color: #339933">=</span><span style="color: #000088">$label</span><span style="color: #339933">;</span>
		<span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">id</span><span style="color: #339933">=</span><span style="color: #000088">$id</span><span style="color: #339933">;</span>
	<span style="color: #009900">}</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> hasMenuOptionId<span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">{</span>
		<span style="color: #b1b100">return</span> <span style="color: #000088">$id</span><span style="color: #339933">==</span><span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">id</span><span style="color: #339933">;</span>
	<span style="color: #009900">}</span>
 
	<span style="color: #000000;font-weight: bold">public</span> <span style="color: #000000;font-weight: bold">function</span> MarkPathToMenuOption<span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">{</span>
		<span style="color: #b1b100">if</span> <span style="color: #009900">(</span><span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">hasMenuOptionId</span><span style="color: #009900">(</span><span style="color: #000088">$id</span><span style="color: #009900">)</span><span style="color: #009900">)</span> <span style="color: #000088">$this</span><span style="color: #339933">-></span><span style="color: #004000">mark</span><span style="color: #009900">(</span><span style="color: #009900">)</span><span style="color: #339933">;</span>
	<span style="color: #009900">}</span>
<span style="color: #009900">}</span>
 
<span style="color: #000000;font-weight: bold">?></span>

/*以上方法就是演示了组合模式的使用,当然了,主要是要看menu类,没有迭代循环的更加明显。
* 记住我的PHP进阶群号:63417682*/