├── .DS_Store ├── .github └── FUNDING.yml ├── book ├── .DS_Store ├── archetypes │ └── default.md ├── config.yaml ├── content │ ├── .DS_Store │ ├── _index.md │ └── docs │ │ ├── chapter1.md │ │ ├── chapter10.md │ │ ├── chapter11.md │ │ ├── chapter12.md │ │ ├── chapter13.md │ │ ├── chapter14.md │ │ ├── chapter15.md │ │ ├── chapter16.md │ │ ├── chapter17.md │ │ ├── chapter18.md │ │ ├── chapter19.md │ │ ├── chapter2.md │ │ ├── chapter20.md │ │ ├── chapter21.md │ │ ├── chapter22.md │ │ ├── chapter23.md │ │ ├── chapter24.md │ │ ├── chapter25.md │ │ ├── chapter26.md │ │ ├── chapter27.md │ │ ├── chapter28.md │ │ ├── chapter29.md │ │ ├── chapter3.md │ │ ├── chapter4.md │ │ ├── chapter5.md │ │ ├── chapter6.md │ │ ├── chapter7.md │ │ ├── chapter8.md │ │ ├── chapter9.md │ │ └── 序言.md ├── public │ ├── 404.html │ ├── book.min.134b70e5316650a530cb42e4e8630b2a01d532bebfc0337028211175336e4806.css │ ├── categories │ │ ├── index.html │ │ └── index.xml │ ├── docs │ │ ├── chapter1 │ │ │ └── index.html │ │ ├── chapter10 │ │ │ └── index.html │ │ ├── chapter11 │ │ │ └── index.html │ │ ├── chapter12 │ │ │ └── index.html │ │ ├── chapter13 │ │ │ └── index.html │ │ ├── chapter14 │ │ │ └── index.html │ │ ├── chapter15 │ │ │ └── index.html │ │ ├── chapter16 │ │ │ └── index.html │ │ ├── chapter17 │ │ │ └── index.html │ │ ├── chapter18 │ │ │ └── index.html │ │ ├── chapter19 │ │ │ └── index.html │ │ ├── chapter2 │ │ │ └── index.html │ │ ├── chapter20 │ │ │ └── index.html │ │ ├── chapter21 │ │ │ └── index.html │ │ ├── chapter22 │ │ │ └── index.html │ │ ├── chapter23 │ │ │ └── index.html │ │ ├── chapter24 │ │ │ └── index.html │ │ ├── chapter25 │ │ │ └── index.html │ │ ├── chapter26 │ │ │ └── index.html │ │ ├── chapter27 │ │ │ └── index.html │ │ ├── chapter28 │ │ │ └── index.html │ │ ├── chapter29 │ │ │ └── index.html │ │ ├── chapter3 │ │ │ └── index.html │ │ ├── chapter4 │ │ │ └── index.html │ │ ├── chapter5 │ │ │ └── index.html │ │ ├── chapter6 │ │ │ └── index.html │ │ ├── chapter7 │ │ │ └── index.html │ │ ├── chapter8 │ │ │ └── index.html │ │ ├── chapter9 │ │ │ └── index.html │ │ ├── index.html │ │ ├── index.xml │ │ └── 序言 │ │ │ └── index.html │ ├── en.search-data.min.527444053051030881c267eb7bed3324c34112619e4bd7041755fd3ff22e337e.js │ ├── en.search.min.9e32b36e065fcc0a76dade0cc47798d1533be64df6d2282bd5b4fb040caf152d.js │ ├── favicon.png │ ├── favicon.svg │ ├── flexsearch.min.js │ ├── fonts │ │ ├── roboto-mono-v6-latin-regular.woff │ │ ├── roboto-mono-v6-latin-regular.woff2 │ │ ├── roboto-v19-latin-300italic.woff │ │ ├── roboto-v19-latin-300italic.woff2 │ │ ├── roboto-v19-latin-700.woff │ │ ├── roboto-v19-latin-700.woff2 │ │ ├── roboto-v19-latin-regular.woff │ │ └── roboto-v19-latin-regular.woff2 │ ├── index.html │ ├── index.xml │ ├── katex │ │ ├── auto-render.min.js │ │ ├── fonts │ │ │ ├── KaTeX_AMS-Regular.ttf │ │ │ ├── KaTeX_AMS-Regular.woff │ │ │ ├── KaTeX_AMS-Regular.woff2 │ │ │ ├── KaTeX_Caligraphic-Bold.ttf │ │ │ ├── KaTeX_Caligraphic-Bold.woff │ │ │ ├── KaTeX_Caligraphic-Bold.woff2 │ │ │ ├── KaTeX_Caligraphic-Regular.ttf │ │ │ ├── KaTeX_Caligraphic-Regular.woff │ │ │ ├── KaTeX_Caligraphic-Regular.woff2 │ │ │ ├── KaTeX_Fraktur-Bold.ttf │ │ │ ├── KaTeX_Fraktur-Bold.woff │ │ │ ├── KaTeX_Fraktur-Bold.woff2 │ │ │ ├── KaTeX_Fraktur-Regular.ttf │ │ │ ├── KaTeX_Fraktur-Regular.woff │ │ │ ├── KaTeX_Fraktur-Regular.woff2 │ │ │ ├── KaTeX_Main-Bold.ttf │ │ │ ├── KaTeX_Main-Bold.woff │ │ │ ├── KaTeX_Main-Bold.woff2 │ │ │ ├── KaTeX_Main-BoldItalic.ttf │ │ │ ├── KaTeX_Main-BoldItalic.woff │ │ │ ├── KaTeX_Main-BoldItalic.woff2 │ │ │ ├── KaTeX_Main-Italic.ttf │ │ │ ├── KaTeX_Main-Italic.woff │ │ │ ├── KaTeX_Main-Italic.woff2 │ │ │ ├── KaTeX_Main-Regular.ttf │ │ │ ├── KaTeX_Main-Regular.woff │ │ │ ├── KaTeX_Main-Regular.woff2 │ │ │ ├── KaTeX_Math-BoldItalic.ttf │ │ │ ├── KaTeX_Math-BoldItalic.woff │ │ │ ├── KaTeX_Math-BoldItalic.woff2 │ │ │ ├── KaTeX_Math-Italic.ttf │ │ │ ├── KaTeX_Math-Italic.woff │ │ │ ├── KaTeX_Math-Italic.woff2 │ │ │ ├── KaTeX_SansSerif-Bold.ttf │ │ │ ├── KaTeX_SansSerif-Bold.woff │ │ │ ├── KaTeX_SansSerif-Bold.woff2 │ │ │ ├── KaTeX_SansSerif-Italic.ttf │ │ │ ├── KaTeX_SansSerif-Italic.woff │ │ │ ├── KaTeX_SansSerif-Italic.woff2 │ │ │ ├── KaTeX_SansSerif-Regular.ttf │ │ │ ├── KaTeX_SansSerif-Regular.woff │ │ │ ├── KaTeX_SansSerif-Regular.woff2 │ │ │ ├── KaTeX_Script-Regular.ttf │ │ │ ├── KaTeX_Script-Regular.woff │ │ │ ├── KaTeX_Script-Regular.woff2 │ │ │ ├── KaTeX_Size1-Regular.ttf │ │ │ ├── KaTeX_Size1-Regular.woff │ │ │ ├── KaTeX_Size1-Regular.woff2 │ │ │ ├── KaTeX_Size2-Regular.ttf │ │ │ ├── KaTeX_Size2-Regular.woff │ │ │ ├── KaTeX_Size2-Regular.woff2 │ │ │ ├── KaTeX_Size3-Regular.ttf │ │ │ ├── KaTeX_Size3-Regular.woff │ │ │ ├── KaTeX_Size3-Regular.woff2 │ │ │ ├── KaTeX_Size4-Regular.ttf │ │ │ ├── KaTeX_Size4-Regular.woff │ │ │ ├── KaTeX_Size4-Regular.woff2 │ │ │ ├── KaTeX_Typewriter-Regular.ttf │ │ │ ├── KaTeX_Typewriter-Regular.woff │ │ │ └── KaTeX_Typewriter-Regular.woff2 │ │ ├── katex.min.css │ │ └── katex.min.js │ ├── manifest.json │ ├── mermaid.min.js │ ├── sitemap.xml │ ├── svg │ │ ├── calendar.svg │ │ ├── edit.svg │ │ ├── menu.svg │ │ ├── toc.svg │ │ └── translate.svg │ └── tags │ │ ├── index.html │ │ └── index.xml └── resources │ └── _gen │ └── assets │ └── scss │ ├── book.scss_50fc8c04e12a2f59027287995557ceff.content │ └── book.scss_50fc8c04e12a2f59027287995557ceff.json ├── codes ├── AbstractFactory.php ├── Adapter.php ├── Bridge.php ├── Builder.php ├── ChainOfResponsibility.php ├── Clone.php ├── Command.php ├── Composite.php ├── CompositeCompany.php ├── Decorator.php ├── Decorator2.php ├── Facade.php ├── FactoryMethod.php ├── Flyweight.php ├── Interpreter.php ├── Iterator.php ├── Mediator.php ├── Memento.php ├── Observer.php ├── Operation.php ├── Proxy.php ├── Singleton.php ├── State.php ├── Strategy.php ├── Template.php └── Visitor.php ├── files ├── .DS_Store ├── chapter1.md ├── chapter10.md ├── chapter11.md ├── chapter12.md ├── chapter13.md ├── chapter14.md ├── chapter15.md ├── chapter16.md ├── chapter17.md ├── chapter18.md ├── chapter19.md ├── chapter2.md ├── chapter20.md ├── chapter21.md ├── chapter22.md ├── chapter23.md ├── chapter24.md ├── chapter25.md ├── chapter26.md ├── chapter27.md ├── chapter28.md ├── chapter29.md ├── chapter3.md ├── chapter4.md ├── chapter5.md ├── chapter6.md ├── chapter7.md ├── chapter8.md ├── chapter9.md └── chpter24.md ├── images ├── .DS_Store ├── decorator.png └── sponsor.jpeg └── readme.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/.DS_Store -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [flyingalex] 2 | custom: https://github.com/flyingalex/design-patterns-by-php/blob/master/images/sponsor.jpeg 3 | 4 | -------------------------------------------------------------------------------- /book/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/.DS_Store -------------------------------------------------------------------------------- /book/archetypes/default.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "{{ replace .Name "-" " " | title }}" 3 | date: {{ .Date }} 4 | draft: true 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /book/config.yaml: -------------------------------------------------------------------------------- 1 | baseURL: "https://design-patterns-by-php.hulin.ink/" 2 | languageCode: "en-us" 3 | title: "design-patterns-by-php" 4 | theme: "book" -------------------------------------------------------------------------------- /book/content/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/content/.DS_Store -------------------------------------------------------------------------------- /book/content/_index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 序言 3 | type: docs 4 | --- 5 | 6 | [《大话设计模式》](https://book.douban.com/subject/2334288/)php版本 7 | 用自己现在用的语言重新写一遍,文中的代码均可以在终端内执行 8 | 9 | 相关资源: 10 | 11 | [Design Patterns for Humans](https://github.com/kamranahmedse/design-patterns-for-humans) 12 | 13 | [DesignPatternsPHP](https://github.com/domnikl/DesignPatternsPHP) 14 | ## 目录 15 | 16 | - [第一章 代码无错就是优 ---简单工厂模式]({{< relref "/docs/chapter1" >}}) 17 | 18 | - [第二章 商场促销 --- 策略模式]({{< relref "/docs/chapter2" >}}) 19 | 20 | - [第三章 拍摄UFO --- 单一职责原则]({{< relref "/docs/chapter3" >}}) 21 | 22 | - [第四章 研求职两不误 --- 开放-封闭原则]({{< relref "/docs/chapter4" >}}) 23 | 24 | - [第五章 会修电脑不会修收音机? --- 依赖倒转原则]({{< relref "/docs/chapter5" >}}) 25 | 26 | - [第六章 穿什么有这么重要吗 --- 装饰模式]({{< relref "/docs/chapter6" >}}) 27 | 28 | - [第七章 为别人做嫁衣 --- 代理模式]({{< relref "/docs/chapter7" >}}) 29 | 30 | - [第八章 雷锋依然在人间 --- 工厂方法模式]({{< relref "/docs/chapter8" >}}) 31 | 32 | - [第九章 简历复印 --- 原型模式]({{< relref "/docs/chapter9" >}}) 33 | 34 | - [第十章 考题抄错会做也白搭 --- 模版方法模式]({{< relref "/docs/chapter10" >}}) 35 | 36 | - [第十一章 无熟人难办事 --- 迪米特法则]({{< relref "/docs/chapter11" >}}) 37 | 38 | - [第十二章 牛市股票还会亏钱 --- 外观模式]({{< relref "/docs/chapter12" >}}) 39 | 40 | - [第十三章 好菜每回味不同 --- 建造者模式]({{< relref "/docs/chapter13" >}}) 41 | 42 | - [第十四章 老板回来,我不知道 --- 观察者模式]({{< relref "/docs/chapter14" >}}) 43 | 44 | - [第十五章 就不能不换DB吗? --- 抽象工厂模式]({{< relref "/docs/chapter5" >}}) 45 | 46 | - [第十六章 无尽加班何时休 --- 状态模式]({{< relref "/docs/chapter16" >}}) 47 | 48 | - [第十七章 在NBA我需要翻译 --- 适配器模式]({{< relref "/docs/chapter17" >}}) 49 | 50 | - [第十八章 如果再回到从前 --- 备忘录模式]({{< relref "/docs/chapter18" >}}) 51 | 52 | - [第十九章 分公司 = 一部分 --- 组合模式]({{< relref "/docs/chapter19" >}}) 53 | 54 | - [第二十章 想走?可以!先买票 --- 迭代器模式]({{< relref "/docs/chapter20" >}}) 55 | 56 | - [第二十一章 有些类也需要计划生育 --- 单例模式]({{< relref "/docs/chapter21" >}}) 57 | 58 | - [第二十二章 手机软件何时统一 --- 桥接模式]({{< relref "/docs/chapter22" >}}) 59 | 60 | - [第二十三章 烤羊肉串引来的思考 --- 命令模式]({{< relref "/docs/chapter23" >}}) 61 | 62 | - [第二十四章 加薪非要老总批 --- 职责链模式]({{< relref "/docs/chapter24" >}}) 63 | 64 | - [第二十五章 世界需要和平 --- 中介者模式]({{< relref "/docs/chapter25" >}}) 65 | 66 | - [第二十六章 项目多也别傻做 --- 享元模式]({{< relref "/docs/chapter26" >}}) 67 | 68 | - [第二十七章 其实你不懂老板的心 --- 解释器模式]({{< relref "/docs/chapter27" >}}) 69 | 70 | - [第二十八章 男人和女人 --- 访问者模式]({{< relref "/docs/chapter28" >}}) 71 | 72 | - [第二十九章 OOTV杯超级模式大赛 --- 模式总结]({{< relref "/docs/chapter29" >}}) 73 | 74 | 75 | ## License 76 | 77 | The MIT License. 78 | -------------------------------------------------------------------------------- /book/content/docs/chapter1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第一章 代码无错就是优 --- 简单工厂模式 3 | type: docs 4 | weight: 2 5 | --- 6 | 7 | ### 第一章 代码无错就是优 --- 简单工厂模式 8 | 9 | 1.简单工厂模式 10 | ```php 11 | a = $a; 24 | } 25 | 26 | public function setB($b) 27 | { 28 | $this->b = $b; 29 | } 30 | 31 | public function getResult() 32 | { 33 | $result = 0; 34 | return $result; 35 | } 36 | } 37 | 38 | /** 39 | * Add 40 | */ 41 | class OperationAdd extends Operation 42 | { 43 | public function getResult() 44 | { 45 | return $this->a + $this->b; 46 | } 47 | } 48 | 49 | /** 50 | * Mul 51 | */ 52 | class OperationMul extends Operation 53 | { 54 | public function getResult() 55 | { 56 | return $this->a * $this->b; 57 | } 58 | } 59 | 60 | /** 61 | * Sub 62 | */ 63 | class OperationSub extends Operation 64 | { 65 | public function getResult() 66 | { 67 | return $this->a - $this->b; 68 | } 69 | } 70 | 71 | /** 72 | * Div 73 | */ 74 | class OperationDiv extends Operation 75 | { 76 | public function getResult() 77 | { 78 | return $this->a / $this->b; 79 | } 80 | } 81 | 82 | /** 83 | * Operation Factory 84 | */ 85 | class OperationFactory 86 | { 87 | public static function createOperation($operation) 88 | { 89 | switch ($operation) { 90 | case '+': 91 | $oper = new OperationAdd(); 92 | break; 93 | case '-': 94 | $oper = new OperationSub(); 95 | break; 96 | case '/': 97 | $oper = new OperationDiv(); 98 | break; 99 | case '*': 100 | $oper = new OperationMul(); 101 | break; 102 | } 103 | 104 | return $oper; 105 | } 106 | } 107 | 108 | // 客户端代码 109 | $operation = OperationFactory::createOperation('+'); 110 | $operation->setA(1); 111 | $operation->setB(2); 112 | echo $operation->getResult() . PHP_EOL; 113 | ``` 114 | 115 | 116 | 117 | 总结 118 | 119 | > 学会通过分封装,继承,多态把程序的藕合度降低 120 | 121 | > 复用,不是复制! 122 | 123 | > 高内聚,低耦合 124 | 125 | 下一章:[第二章 商场促销 --- 策略模式]({{< relref "/docs/chapter2" >}}) 126 | -------------------------------------------------------------------------------- /book/content/docs/chapter10.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十章 考题抄错会做也白搭 --- 模版方法模式 3 | type: docs 4 | weight: 11 5 | --- 6 | 7 | ### 第十章 考题抄错会做也白搭 --- 模版方法模式 8 | ```php 9 | answer1()."\n"; 18 | } 19 | 20 | public function TestQuestion2() 21 | { 22 | echo "杨过、程英、陆无双铲除了情花,造成[]a.使这种植物不在害人 b.使一种珍惜物种灭绝 c.破坏了那个生态圈的生态平衡 d.造成该地区沙漠化 \n"; 23 | echo "答案 ".$this->answer2()."\n"; 24 | } 25 | 26 | public function TestQuestion3() 27 | { 28 | echo "蓝凤凰致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[]a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对 \n"; 29 | echo "答案 ".$this->answer3()."\n"; 30 | } 31 | 32 | protected function answer1() 33 | { 34 | return ''; 35 | } 36 | 37 | protected function answer2() 38 | { 39 | return ''; 40 | } 41 | 42 | protected function answer3() 43 | { 44 | return ''; 45 | } 46 | } 47 | 48 | // 学生甲抄的试卷 49 | class TestPaperA extends TestPaper 50 | { 51 | protected function answer1() 52 | { 53 | return 'a'; 54 | } 55 | 56 | protected function answer2() 57 | { 58 | return 'b'; 59 | } 60 | 61 | protected function answer3() 62 | { 63 | return 'c'; 64 | } 65 | } 66 | 67 | // 学生乙抄的试卷 68 | // 学生甲抄的试卷 69 | class TestPaperB extends TestPaper 70 | { 71 | protected function answer1() 72 | { 73 | return 'd'; 74 | } 75 | 76 | protected function answer2() 77 | { 78 | return 'c'; 79 | } 80 | 81 | protected function answer3() 82 | { 83 | return 'a'; 84 | } 85 | } 86 | 87 | 88 | // 客户端代码 89 | 90 | echo "学生甲抄的试卷: \n"; 91 | $student = new TestPaperA(); 92 | $student->TestQuestion1(); 93 | $student->TestQuestion2(); 94 | $student->TestQuestion3(); 95 | echo "学生乙抄的试卷: \n"; 96 | $student2 = new TestPaperB(); 97 | $student2->TestQuestion1(); 98 | $student2->TestQuestion2(); 99 | $student2->TestQuestion3(); 100 | ``` 101 | 102 | 总结: 103 | 104 | > ***模版方法模式***,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变算法的节结构即可重定义该算法的某些特定步骤。 105 | 106 | > 既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模版,所有重复的代码都应该要上升到父类去,而不是让每个子类去重复。 107 | 108 | > 当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其中个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模版方法模式来处理。 109 | 110 | > 模版方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势。提供了一个很好的代码复用平台。 111 | 112 | > 当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。通过模版方法把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。 113 | 114 | 上一章:[第九章 简历复印 --- 原型模式]({{< relref "/docs/chapter9" >}}) 115 | 116 | 下一章:[第十一章 无熟人难办事 --- 迪米特法则]({{< relref "/docs/chapter11" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter11.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十一章 无熟人难办事 --- 迪米特法则 3 | type: docs 4 | weight: 12 5 | --- 6 | 7 | ### 第十一章 无熟人难办事 --- 迪米特法则 8 | 9 | 总结: 10 | 11 | > ***迪米特法则***,如果两个类不彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。 12 | 13 | > 在类的结构设计上,每一个类都应当 尽量降低成员的访问权限 14 | 15 | > 类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。 16 | 17 | 18 | 上一章:[第十章 考题抄错会做也白搭 --- 模版方法模式]({{< relref "/docs/chapter10" >}}) 19 | 20 | 下一章:[第十二章 牛市股票还会亏钱 --- 外观模式]({{< relref "/docs/chapter12" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter12.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十二章 牛市股票还会亏钱 --- 外观模式 3 | type: docs 4 | weight: 13 5 | --- 6 | 7 | ### 第十二章 牛市股票还会亏钱 --- 外观模式 8 | 9 | ```php 10 | systemOne = new SubSystemOne(); 60 | $this->systemTwo = new SubSystemTwo(); 61 | $this->systemThree = new SubSystemThree(); 62 | $this->systemFour = new SubSystemFourth(); 63 | } 64 | 65 | public function methodA() 66 | { 67 | echo "方法A() ---\n"; 68 | $this->systemOne->methodOne(); 69 | $this->systemThree->methodThree(); 70 | } 71 | 72 | public function methodB() 73 | { 74 | echo "方法B() ---\n"; 75 | $this->systemTwo->methodTwo(); 76 | $this->systemFour->methodFourth(); 77 | } 78 | } 79 | 80 | //客户端代码 81 | 82 | $facade = new Facade(); 83 | $facade->methodA(); 84 | $facade->methodB(); 85 | 86 | ``` 87 | 88 | 总结: 89 | 90 | > ***外观模式***,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更容易使用。 91 | 92 | > 首先,在设计初期阶段,应该要有意识的将不同的两个层分离,层与层之间建立外观Facade;其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖;另外在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作 93 | 94 | 上一章:[第十一章 无熟人难办事 --- 迪米特法则]({{< relref "/docs/chapter11" >}}) 95 | 96 | 下一章:[第十三章 好菜每回味不同 --- 建造者模式]({{< relref "/docs/chapter13" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter13.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十三章 好菜每回味不同 --- 建造者模式 3 | type: docs 4 | weight: 14 5 | --- 6 | 7 | ### 第十三章 好菜每回味不同 --- 建造者模式 8 | 9 | ```php 10 | personBuilder = $personBuilder; 96 | } 97 | 98 | public function CreatePerson() 99 | { 100 | $this->personBuilder->BuildHead(); 101 | $this->personBuilder->BuildBody(); 102 | $this->personBuilder->BuildArmRight(); 103 | $this->personBuilder->BuildArmLeft(); 104 | $this->personBuilder->BuildLegLeft(); 105 | $this->personBuilder->BuildLegRight(); 106 | } 107 | } 108 | 109 | 110 | //客户端代码 111 | 112 | echo "苗条的:\n"; 113 | $thinDirector = new PersonDirector(new PersonThinBuilder()); 114 | $thinDirector->CreatePerson(); 115 | 116 | echo "\n胖的:\n"; 117 | $fatDirector = new PersonDirector(new PersonFatBuilder()); 118 | $fatDirector->CreatePerson(); 119 | ``` 120 | 121 | 总结: 122 | 123 | > ***建造者模式***,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 124 | 125 | > 如果我们用了建造者模式,那么用户只需要指定需要建造的类型就可以得到他们,而具体建造的过程和细节就不需要知道了。 126 | 127 | > 主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通畅面临着复杂的变化。 128 | 129 | > 建造者模式是在当创建复杂对象的算法应该独立于改对象的组成部分以及它们的装配方式时适用的模式。 130 | 131 | 上一章:[第十二章 牛市股票还会亏钱 --- 外观模式]({{< relref "/docs/chapter12" >}}) 132 | 133 | 下一章:[第十四章 老板回来,我不知道 --- 观察者模式]({{< relref "/docs/chapter14" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter14.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十四章 老板回来,我不知道 --- 观察者模式 3 | type: docs 4 | weight: 15 5 | --- 6 | 7 | ### 第十四章 老板回来,我不知道 --- 观察者模式 8 | 9 | ```php 10 | observers, $observer); 19 | } 20 | 21 | public function detatch($observer) 22 | { 23 | foreach ($this->observers as $key => $value) { 24 | if ($observer === $value) { 25 | unset($this->observers[$key]); 26 | } 27 | } 28 | } 29 | 30 | public function notify() 31 | { 32 | foreach ($this->observers as $observer) { 33 | $observer->update(); 34 | } 35 | } 36 | } 37 | 38 | abstract class Observer 39 | { 40 | abstract function update(); 41 | } 42 | 43 | class ConcreteSubject extends Subject 44 | { 45 | private $subjectState; 46 | public function setState($state) 47 | { 48 | $this->subjectState = $state; 49 | } 50 | 51 | public function getState() 52 | { 53 | return $this->subjectState; 54 | } 55 | } 56 | 57 | class ConcreteObserver extends Observer 58 | { 59 | private $name; 60 | private $subject; 61 | 62 | function __construct(ConcreteSubject $subject, $name) 63 | { 64 | $this->subject = $subject; 65 | $this->name = $name; 66 | } 67 | 68 | public function update() 69 | { 70 | echo "观察者 ".$this->name."的新状态是:".$this->subject->getState()."\n"; 71 | } 72 | } 73 | 74 | $s = new ConcreteSubject(); 75 | $s->attach(new ConcreteObserver($s, "x")); 76 | $s->attach(new ConcreteObserver($s, "y")); 77 | $z = new ConcreteObserver($s, "z"); 78 | $s->attach($z); 79 | $s->detatch($z); 80 | $s->setState('ABC'); 81 | $s->notify(); 82 | ``` 83 | 84 | 总结: 85 | > ***观察者模式***,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 86 | 87 | > 将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。 88 | 89 | > 观察者模式所做的工作其实就是在接触耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。 90 | 91 | 上一章:[第十三章 好菜每回味不同 --- 建造者模式]({{< relref "/docs/chapter13" >}}) 92 | 93 | 下一章:[第十五章 就不能不换DB吗? --- 抽象工厂模式]({{< relref "/docs/chapter15" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter16.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十六章 无尽加班何时休 --- 状态模式 3 | type: docs 4 | weight: 17 5 | --- 6 | 7 | ### 第十六章 无尽加班何时休 --- 状态模式 8 | 9 | ```php 10 | //工作状态 11 | abstract class State 12 | { 13 | abstract public function WriteProgram(Work $w); 14 | } 15 | 16 | class ForenoonState extends State 17 | { 18 | public function WriteProgram(Work $w) 19 | { 20 | if ($w->getHour() < 12) { 21 | echo "当前时间:".$w->getHour()." 上午工作,精神百倍\n"; 22 | } else { 23 | $w->setState(new NoonState()); 24 | $w->WriteProgram(); 25 | } 26 | } 27 | } 28 | 29 | class NoonState extends State 30 | { 31 | public function WriteProgram(Work $w) 32 | { 33 | if ($w->getHour() < 13) { 34 | echo "当前时间:".$w->getHour()." 饿了,午饭;犯困,午休\n"; 35 | } else { 36 | $w->setState(new AfterNoonState()); 37 | $w->WriteProgram(); 38 | } 39 | } 40 | } 41 | 42 | class AfterNoonState extends State 43 | { 44 | public function WriteProgram(Work $w) 45 | { 46 | if ($w->getHour() < 17) { 47 | echo "当前时间:".$w->getHour()." 下午状态不错,继续努力\n"; 48 | } else { 49 | $w->setState(new EveningState()); 50 | $w->WriteProgram(); 51 | } 52 | } 53 | } 54 | 55 | class EveningState extends State 56 | { 57 | public function WriteProgram(Work $w) 58 | { 59 | if ($w->getTaskFinishedState()) { 60 | //如果完成任务,下班 61 | $w->setState(new RestState()); 62 | $w->WriteProgram(); 63 | } else { 64 | if ($w->getHour() < 21) { 65 | echo "当前时间:".$w->getHour()." 加班哦,疲惫之极\n"; 66 | } else { 67 | //超过21点,则转入睡眠工作状态 68 | $w->setState(new SleepingState()); 69 | $w->WriteProgram(); 70 | } 71 | } 72 | } 73 | } 74 | 75 | class SleepingState extends State 76 | { 77 | public function WriteProgram(Work $w) 78 | { 79 | echo "当前时间:".$w->getHour()." 不行了,睡觉\n"; 80 | } 81 | } 82 | 83 | class RestState extends State 84 | { 85 | public function WriteProgram(Work $w) 86 | { 87 | echo "当前时间:".$w->getHour()." 下班回家\n"; 88 | } 89 | } 90 | 91 | class Work 92 | { 93 | private $current; 94 | 95 | function __construct() 96 | { 97 | $this->current = new ForenoonState(); 98 | } 99 | 100 | private $hour; 101 | public function getHour() 102 | { 103 | return $this->hour; 104 | } 105 | public function setHour($hour) 106 | { 107 | $this->hour = $hour; 108 | } 109 | 110 | private $finished = false; 111 | public function setTaskFinished($bool) 112 | { 113 | $this->finished = $bool; 114 | } 115 | public function getTaskFinishedState() 116 | { 117 | return $this->finished; 118 | } 119 | 120 | public function setState(State $state) 121 | { 122 | $this->current = $state; 123 | } 124 | 125 | public function WriteProgram() 126 | { 127 | $this->current->WriteProgram($this); 128 | } 129 | } 130 | 131 | //客户端代码 132 | $emergencyProjects = new Work(); 133 | $emergencyProjects->setHour(9); 134 | $emergencyProjects->WriteProgram(); 135 | $emergencyProjects->setHour(10); 136 | $emergencyProjects->WriteProgram(); 137 | $emergencyProjects->setHour(12); 138 | $emergencyProjects->WriteProgram(); 139 | $emergencyProjects->setHour(13); 140 | $emergencyProjects->WriteProgram(); 141 | $emergencyProjects->setHour(14); 142 | $emergencyProjects->WriteProgram(); 143 | $emergencyProjects->setHour(17); 144 | 145 | $emergencyProjects->setTaskFinished(false); 146 | $emergencyProjects->WriteProgram(); 147 | 148 | $emergencyProjects->setHour(19); 149 | $emergencyProjects->WriteProgram(); 150 | $emergencyProjects->setHour(22); 151 | $emergencyProjects->WriteProgram(); 152 | 153 | ``` 154 | 155 | 总结: 156 | 157 | > ***状态模式***,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。 158 | 159 | > 面向对象设计其实就是希望做到代码的责任分解。 160 | 161 | > 状态模式主要解决的当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简单化。 162 | 163 | > 将于特定状态相关的行为局部化,并且将不同状态的行为分割开来。 164 | 165 | > 将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义的子类可以很容易地增加新的状态和转换。 166 | 167 | > 消除了庞大的条件分支语句。 168 | 169 | > 状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少项目之间的依赖。 170 | 171 | > 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。 172 | 173 | 174 | 上一章:[第十五章 就不能不换DB吗? --- 抽象工厂模式]({{< relref "/docs/chapter15" >}}) 175 | 176 | 下一章:[第十七章 在NBA我需要翻译 --- 适配器模式]({{< relref "/docs/chapter17" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter17.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十七章 在NBA我需要翻译 --- 适配器模式 3 | type: docs 4 | weight: 18 5 | --- 6 | 7 | ### 第十七章 在NBA我需要翻译 --- 适配器模式 8 | 9 | ```php 10 | name = $name; 20 | } 21 | 22 | abstract public function Attack(); 23 | abstract public function Defense(); 24 | } 25 | 26 | //前锋 27 | class Forwards extends Player 28 | { 29 | public function Attack() 30 | { 31 | echo "前锋:".$this->name." 进攻\n"; 32 | } 33 | public function Defense() 34 | { 35 | echo "前锋:".$this->name." 防守\n"; 36 | } 37 | } 38 | 39 | //中锋 40 | class Center extends Player 41 | { 42 | function __construct() 43 | { 44 | parent::__construct(); 45 | } 46 | 47 | public function Attack() 48 | { 49 | echo "中锋:".$this->name." 进攻\n"; 50 | } 51 | public function Defense() 52 | { 53 | echo "中锋:".$this->name." 防守\n"; 54 | } 55 | } 56 | 57 | //外籍中锋 58 | class ForeignCenter 59 | { 60 | private $name; 61 | public function setName($name) 62 | { 63 | $this->name = $name; 64 | } 65 | 66 | public function getName() 67 | { 68 | return $this->name; 69 | } 70 | 71 | public function 进攻() 72 | { 73 | echo "外籍中锋:".$this->name." 进攻\n"; 74 | } 75 | 76 | public function 防守() 77 | { 78 | echo "外籍中锋:".$this->name." 防守\n"; 79 | } 80 | } 81 | 82 | //翻译者 83 | class Translator extends Player 84 | { 85 | private $foreignCenter; 86 | 87 | function __construct($name) 88 | { 89 | $this->foreignCenter = new ForeignCenter(); 90 | $this->foreignCenter->setName($name); 91 | } 92 | 93 | public function Attack() 94 | { 95 | $this->foreignCenter->进攻(); 96 | } 97 | public function Defense() 98 | { 99 | $this->foreignCenter->防守(); 100 | } 101 | 102 | } 103 | 104 | // 客户端代码 105 | $forwards = new Forwards("巴蒂尔"); 106 | $forwards->Attack(); 107 | $forwards->Defense(); 108 | 109 | $translator = new Translator("姚明"); 110 | $translator->Attack(); 111 | $translator->Defense(); 112 | ``` 113 | 114 | 总结: 115 | 116 | > ***适配器模式***,将一个类的接口转化成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 117 | 118 | > 系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类。但是接口又与复用环境要求不一致的情况。 119 | 120 | > 两个类所做的事情相同或相似,但是具有不同的接口时要使用它。 121 | 122 | > 在双方都不太容易修改的时候再使用适配器模式适配。 123 | 124 | 上一章:[第十六章 无尽加班何时休 --- 状态模式]({{< relref "/docs/chapter16" >}}) 125 | 126 | 下一章:[第十八章 如果再回到从前 --- 备忘录模式]({{< relref "/docs/chapter18" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter18.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十八章 如果再回到从前 --- 备忘录模式 3 | type: docs 4 | weight: 19 5 | --- 6 | 7 | ### 第十八章 如果再回到从前 --- 备忘录模式 8 | 9 | ```php 10 | state = $state; 20 | } 21 | public function getState() 22 | { 23 | return $this->state; 24 | } 25 | 26 | //创建备忘录,将当前需要保存的信息导入并实例化出一个memento对象。 27 | public function createMemento() 28 | { 29 | return new Memento($this->state); 30 | } 31 | 32 | //恢复备忘录,将memento导入并将相关数据恢复。 33 | public function setMemento(Memento $memento) 34 | { 35 | $this->state = $memento->getState(); 36 | } 37 | 38 | //显示数据 39 | public function show() 40 | { 41 | echo "status ".$this->state."\n"; 42 | } 43 | } 44 | 45 | //备忘录类 46 | 47 | class Memento 48 | { 49 | private $state; 50 | 51 | //构造方法,将相关数据导入 52 | function __construct($state) 53 | { 54 | $this->state = $state; 55 | } 56 | 57 | //获取需要保存的数据,可以多个 58 | public function getState() 59 | { 60 | return $this->state; 61 | } 62 | } 63 | 64 | //管理者类 65 | class CareTaker 66 | { 67 | private $memento; 68 | 69 | public function getMemento() 70 | { 71 | return $this->memento; 72 | } 73 | 74 | //设置备忘录 75 | public function setMemento(Memento $memento) 76 | { 77 | $this->memento = $memento; 78 | } 79 | } 80 | 81 | //客户端程序 82 | $o = new Originator(); //Originator初始状态,状态属性on 83 | $o->setState("On"); 84 | $o->show(); 85 | 86 | //保存状态时,由于有了很好的封装,可以隐藏Originator的实现细节 87 | $c = new CareTaker(); 88 | $c->setMemento($o->createMemento()); 89 | 90 | // 改变属性 91 | $o->setState("Off"); 92 | $o->show(); 93 | 94 | // 恢复属性 95 | $o->setMemento($c->getMemento()); 96 | $o->show(); 97 | ``` 98 | 99 | 总结: 100 | 101 | > ***备忘录模式***,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之前保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 102 | 103 | > 代码无措未必优 104 | 105 | > 如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。 106 | 107 | > 使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来。 108 | 109 | 110 | 上一章:[第十七章 在NBA我需要翻译 --- 适配器模式]({{< relref "/docs/chapter17" >}}) 111 | 112 | 下一章:[第十九章 分公司 = 一部分 --- 组合模式]({{< relref "/docs/chapter19" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter19.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第十九章 分公司=一部分 --- 组合模式 3 | type: docs 4 | weight: 20 5 | --- 6 | 7 | ### 第十九章 分公司=一部分 --- 组合模式 8 | ```php 9 | name = $name; 19 | } 20 | 21 | //通常用add和remove方法来提供增加或移除树枝货树叶的功能 22 | abstract public function add(Component $c); 23 | abstract public function remove(Component $c); 24 | abstract public function display($depth); 25 | } 26 | 27 | //leaf在组合中表示叶节点对象,叶节点对象没有子节点。 28 | class Leaf extends Component 29 | { 30 | // 由于叶子没有再增加分枝和树叶,所以add和remove方法实现它没有意义, 31 | // 但这样做可以消除叶节点和枝节点对象在抽象层次的区别,它们具有完全一致的接口 32 | public function add(Component $c) 33 | { 34 | echo "can not add to a leaf\n"; 35 | } 36 | 37 | public function remove(Component $c) 38 | { 39 | echo "can not remove to a leaf\n"; 40 | } 41 | 42 | // 叶节点的具体方法,此处是显示其名称和级别 43 | public function display($depth) 44 | { 45 | echo str_repeat('-', $depth).$this->name."\n"; 46 | } 47 | } 48 | 49 | //composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加add和删除remove. 50 | 51 | class Composite extends Component 52 | { 53 | //一个子对象集合用来存储其下属的枝节点和叶节点。 54 | private $childern = []; 55 | 56 | public function add(Component $c) 57 | { 58 | array_push($this->childern, $c); 59 | } 60 | 61 | public function remove(Component $c) 62 | { 63 | foreach ($this->childern as $key => $value) { 64 | if ($c === $value) { 65 | unset($this->childern[$key]); 66 | } 67 | } 68 | } 69 | 70 | // 显示其枝节点名称,并对其下级进行遍历 71 | public function display($depth) 72 | { 73 | echo str_repeat('-', $depth).$this->name."\n"; 74 | foreach ($this->childern as $component) { 75 | $component->display($depth + 2); 76 | } 77 | } 78 | } 79 | 80 | //客户端代码 81 | 82 | $root = new Composite('root'); 83 | $root->add(new Leaf("Leaf A")); 84 | $root->add(new Leaf("Leaf B")); 85 | 86 | $comp = new Composite("Composite X"); 87 | $comp->add(new Leaf("Leaf XA")); 88 | $comp->add(new Leaf("Leaf XB")); 89 | 90 | $root->add($comp); 91 | 92 | $comp2 = new Composite("Composite X"); 93 | $comp2->add(new Leaf("Leaf XA")); 94 | $comp2->add(new Leaf("Leaf XB")); 95 | 96 | $comp->add($comp2); 97 | 98 | $root->add(new Leaf("Leaf C")); 99 | 100 | $leaf = new Leaf("Leaf D"); 101 | $root->add($leaf); 102 | $root->remove($leaf); 103 | 104 | $root->display(1); 105 | ``` 106 | 107 | 总结: 108 | 109 | > ***组合模式***,将对象组合成树形结构以表示‘部分与整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 110 | 111 | > 透明方式,子类的所有接口一致,虽然有些接口没有用。 112 | 113 | > 安全方式,子类接口不一致,只实现特定的接口,但是这样就要做相应的判断,带来了不便。 114 | 115 | > 需求中是体现部分与整体层次的结构时,或希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。 116 | 117 | > 组合模式可以让客户一致地使用组合结构和单个对象。 118 | 119 | 上一章:[第十八章 如果再回到从前 --- 备忘录模式]({{< relref "/docs/chapter18" >}}) 120 | 121 | 下一章:[第二十章 想走?可以!先买票 --- 迭代器模式]({{< relref "/docs/chapter20" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二章 商场促销 --- 策略模式 3 | type: docs 4 | weight: 3 5 | --- 6 | 7 | ### 第二章 商场促销 --- 策略模式 8 | 9 | 1.策略模式 10 | ```php 11 | strategy = $strategy; 66 | } 67 | 68 | public function contextInterface() 69 | { 70 | $this->strategy->AlgorithmInterface(); 71 | } 72 | } 73 | 74 | $context = new Context(new ConcreteStrategyA()); 75 | $context->contextInterface(); 76 | 77 | $context = new Context(new ConcreteStrategyB()); 78 | $context->contextInterface(); 79 | 80 | $context = new Context(new ConcreteStrategyC()); 81 | $context->contextInterface(); 82 | 83 | 84 | ``` 85 | 86 | 2.策略模式和简单工厂结合 87 | ```php 88 | strategy = new ConcreteStrategyA(); 100 | break; 101 | case 'b': 102 | $this->strategy = new ConcreteStrategyB(); 103 | break; 104 | case 'c': 105 | $this->strategy = new ConcreteStrategyC(); 106 | break; 107 | } 108 | } 109 | 110 | public function contextInterface() 111 | { 112 | return $this->strategy->AlgorithmInterface(); 113 | } 114 | } 115 | 116 | //客户端代码 117 | $context = new Context('a'); 118 | $context->contextInterface(); 119 | ``` 120 | 121 | 总结: 122 | > 面向对象的编程,并不是类越多越好,类的划分为了封装,但分类的基础是抽象,具有相同属性和功能的对象集合才是类。 123 | 124 | > 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。 125 | 126 | > 策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中公共功能。 127 | 128 | > 策略模式简化了单元测试,因为每个算法都有自己的类,可以通自己接口单独测试。 129 | 130 | > 当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。将这些行为封装在一个个Strategy类中,可以在使用这些行为的类中消除条件语句。 131 | 132 | > 策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。 133 | 134 | > 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。 135 | 136 | 上一章:[第一章 代码无错就是优 ---简单工厂模式]({{< relref "/docs/chapter1" >}}) 137 | 138 | 下一章:[第三章 拍摄UFO --- 单一职责原则]({{< relref "/docs/chapter3" >}}) 139 | -------------------------------------------------------------------------------- /book/content/docs/chapter20.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十章 想走?可以!先买票 --- 迭代器模式 3 | type: docs 4 | weight: 21 5 | --- 6 | 7 | ### 第二十章 想走?可以!先买票 --- 迭代器模式 8 | 9 | ```php 10 | aggregate = $aggregate; 34 | } 35 | 36 | public function first() 37 | { 38 | return $this->aggregate[0]; 39 | } 40 | 41 | public function next() 42 | { 43 | $ret = null; 44 | $this->current++; 45 | if ($this->current < count($this->aggregate)) 46 | { 47 | $ret = $this->aggregate[$this->current]; 48 | } 49 | return $ret; 50 | } 51 | 52 | public function isDone() 53 | { 54 | return $this->current >= count($this->aggregate); 55 | } 56 | 57 | public function currentItem() 58 | { 59 | return $this->aggregate[$this->current]; 60 | } 61 | } 62 | 63 | //这个类的代码感觉不符合书上的写法,但我感觉书上的不对,可能我知识面太单薄,没读懂,可自行参阅原著😊。 64 | class ConcreteAggregate extends Aggregate 65 | { 66 | private $items = []; 67 | 68 | public function createIterator() 69 | { 70 | return new ConcreteIterator($this); 71 | } 72 | 73 | public function count() 74 | { 75 | return count($this->items); 76 | } 77 | 78 | public function add($item) 79 | { 80 | array_push($this->items, $item); 81 | } 82 | 83 | public function items() 84 | { 85 | return $this->items; 86 | } 87 | } 88 | 89 | //客户端代码 90 | $a = new ConcreteAggregate(); 91 | $a->add("大鸟"); 92 | $a->add("小菜"); 93 | $a->add("行李"); 94 | $a->add("老外"); 95 | $a->add("公交内部员工"); 96 | $a->add("小偷"); 97 | 98 | $i = new ConcreteIterator($a->items()); 99 | 100 | while (!$i->isDone()) 101 | { 102 | echo $i->currentItem()." 请买票\n"; 103 | $i->next(); 104 | } 105 | ``` 106 | 107 | 总结: 108 | 109 | > 当你需要对聚集有多种方式遍历时,可以考虑用迭代器模式。 110 | 111 | > 当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。 112 | 113 | > 为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。 114 | 115 | > 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合内部的结构,又可让外部代码透明地访问集合内部的数据。 116 | 117 | 118 | 上一章:[第十九章 分公司 = 一部分 --- 组合模式]({{< relref "/docs/chapter19" >}}) 119 | 120 | 下一章:[第二十一章 有些类也需要计划生育 --- 单例模式]({{< relref "/docs/chapter21" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter21.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十一章 有些类也需要计划生育 --- 单例模式 3 | type: docs 4 | weight: 22 5 | --- 6 | 7 | ### 第二十一章 有些类也需要计划生育 --- 单例模式 8 | 9 | ```php 10 | ***单例模式***,保证一个类仅有一个实例,并提供一个访问它的全局访问点。 43 | 44 | > 单例模式因为Singleton类封装它的唯一实例,这样它可以严格地控制客户怎样访问以及何时访问它。简单地说就是对唯一实例的受控访问。 45 | 46 | 47 | 上一章:[第二十章 想走?可以!先买票 --- 迭代器模式]({{< relref "/docs/chapter20" >}}) 48 | 49 | 下一章:[第二十二章 手机软件何时统一 --- 桥接模式]({{< relref "/docs/chapter22" >}}) 50 | -------------------------------------------------------------------------------- /book/content/docs/chapter22.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十二章 手机软件何时统 --- 桥接模式 3 | type: docs 4 | weight: 23 5 | --- 6 | 7 | ### 第二十二章 手机软件何时统 --- 桥接模式 8 | 9 | ```php 10 | soft = $soft; 46 | } 47 | 48 | //运行 49 | abstract public function run(); 50 | } 51 | 52 | // 手机品牌n 53 | class HandsetBrandN extends HandsetBrand 54 | { 55 | public function run() 56 | { 57 | $this->soft->run(); 58 | } 59 | } 60 | 61 | // 手机品牌m 62 | class HandsetBrandM extends HandsetBrand 63 | { 64 | public function run() 65 | { 66 | $this->soft->run(); 67 | } 68 | } 69 | 70 | //客户端调用代码 71 | $ab = new HandsetBrandN(); 72 | $ab->setHandsetSoft(new HandsetGame()); 73 | $ab->run(); 74 | 75 | $ab->setHandsetSoft(new HandsetAddressList()); 76 | $ab->run(); 77 | 78 | $ab = new HandsetBrandM(); 79 | $ab->setHandsetSoft(new HandsetGame()); 80 | $ab->run(); 81 | 82 | $ab->setHandsetSoft(new HandsetAddressList()); 83 | $ab->run(); 84 | ``` 85 | 86 | 总结: 87 | 88 | > 桥接模式,将抽象部分与它的实现部分分离,使它们都可以独立地变化。 89 | 90 | > 合成/聚合复用原则,尽量使用合成/聚合,尽量不要使用类继承。 91 | 92 | > 聚合表示弱的‘拥有’关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的‘拥有’关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。 93 | 94 | > 对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更合适的类替换。这种依赖关系限制了灵活性并最终限制了复用性。 95 | 96 | > 优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。 97 | 98 | > 什么叫抽象与它的实现分离,这并不是说,让抽象类与其派生类分离,因为这没有任何意义。实现指的是抽象类和它的派生类用来实现自己的对象。 99 | 100 | > 实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。 101 | 102 | > 只要真正深入地理解了设计原则,很多设计模式其实就是原则的应用而已,或许在不知不觉中就在使用设计模式了。 103 | 104 | 上一章:[第二十一章 有些类也需要计划生育 --- 单例模式]({{< relref "/docs/chapter21" >}}) 105 | 106 | 下一章:[第二十三章 烤羊肉串引来的思考 --- 命令模式]({{< relref "/docs/chapter23" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter23.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十三章 烤羊肉串引来的思考 --- 命令模式 3 | type: docs 4 | weight: 24 5 | --- 6 | 7 | ### 第二十三章 烤羊肉串引来的思考 --- 命令模式 8 | 9 | ```php 10 | receiver = $receiver; 35 | } 36 | 37 | abstract public function excuteCommand(); 38 | } 39 | 40 | //烤羊肉 41 | class BakeMuttonCommand extends Command 42 | { 43 | public function excuteCommand() 44 | { 45 | $this->receiver->bakeMutton(); 46 | } 47 | } 48 | 49 | //烤鸡翅 50 | class BakeChickenWingCommand extends Command 51 | { 52 | public function excuteCommand() 53 | { 54 | $this->receiver->bakeChickenWing(); 55 | } 56 | } 57 | 58 | //服务员 59 | class Waiter 60 | { 61 | private $commands = []; 62 | 63 | //设置订单 64 | public function setOrder(Command $command) 65 | { 66 | if ($command instanceof BakeChickenWingCommand) 67 | { 68 | echo "服务员: 鸡翅没有了,请点别的烧烤\n"; 69 | } else { 70 | echo "增加订单\n"; 71 | array_push($this->commands, $command); 72 | } 73 | } 74 | 75 | //取消订单 76 | public function cancelOrder(Command $command){} 77 | 78 | //通知执行 79 | public function notify() 80 | { 81 | foreach ($this->commands as $value) { 82 | $value->excuteCommand(); 83 | } 84 | } 85 | } 86 | 87 | //客户端代码 88 | 89 | //开店前准备 90 | $boy = new Barbecuer(); 91 | $bakeMuttonCommand1 = new BakeMuttonCommand($boy); 92 | $bakeMuttonCommand2 = new BakeMuttonCommand($boy); 93 | $bakeChickenWingCommand1 = new BakeChickenWingCommand($boy); 94 | $girl = new Waiter(); 95 | 96 | //开门营业 97 | $girl->setOrder($bakeMuttonCommand1); 98 | $girl->setOrder($bakeMuttonCommand2); 99 | $girl->setOrder($bakeChickenWingCommand1); 100 | $girl->notify(); 101 | ``` 102 | 103 | 总结: 104 | 105 | > ***命令模式***,将 一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 106 | 107 | > 对请求派对或记录请求日志,以及日志可撤销的操作。 108 | 109 | > 优点:第一,能较容易地设计一个命令队列;第二,在需要的情况下,可以较容易地将命令记入日志;第三,允许请求的一方决定是否要否决请求;第四,可以容易地实现对请求的撤销和重做;第五,由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;最重要的是该 模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开。 110 | 111 | > 敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般酒不要急着去实现它,事实上,在需要的时候通过重构实现这个模式并不难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。 112 | 113 | 上一章:[第二十二章 手机软件何时统一 --- 桥接模式]({{< relref "/docs/chapter22" >}}) 114 | 115 | 下一章:[第二十四章 加薪非要老总批 --- 职责链模式]({{< relref "/docs/chapter24" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter24.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十四章 加薪非要老总批 --- 职责链模式 3 | type: docs 4 | weight: 25 5 | --- 6 | 7 | ### 第二十四章 加薪非要老总批 --- 职责链模式 8 | ```php 9 | abstract class Handler 10 | { 11 | protected $successor; 12 | 13 | //设置继承者 14 | public function setSuccessor(Handler $successor) 15 | { 16 | $this->successor = $successor; 17 | } 18 | 19 | //处理请求的抽象方法 20 | abstract function handleRequest(int $request); 21 | } 22 | 23 | //如果可以处理请求,就处理之,否者转发给它的后继者 24 | class ConcreteHandler1 extends Handler 25 | { 26 | public function handleRequest(int $request) 27 | { 28 | if ($request >=0 && $request < 10) 29 | { 30 | echo "ConcreteHandler1 handle it\n"; 31 | } else if ($this->successor != null) { 32 | // 转移 33 | $this->successor->handleRequest($request); 34 | } 35 | } 36 | } 37 | 38 | class ConcreteHandler2 extends Handler 39 | { 40 | public function handleRequest(int $request) 41 | { 42 | if ($request >=10 && $request < 20) 43 | { 44 | echo "ConcreteHandler2 handle it\n"; 45 | } else if ($this->successor != null) { 46 | $this->successor->handleRequest($request); 47 | } 48 | } 49 | } 50 | 51 | // client 52 | $h1 = new ConcreteHandler1(); 53 | $h2 = new ConcreteHandler2(); 54 | 设置职责链上下家 55 | $h1->setSuccessor($h2); 56 | $requests = [1,5,7,16,25]; 57 | 循环给最小处理者提交请求,不同的数额,由不同权限处理者处理 58 | foreach ($requests as $value) { 59 | $h1->handleRequest($value); 60 | } 61 | ``` 62 | 63 | 总结 64 | > ***职责链模式***, 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对像处理它为止。 65 | 66 | > 当用户提交一个请求时,请求是沿着链传递直至有一个对象负责处理它。 67 | 68 | > 接受者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需要保持一个向其后继者的引用,而不需要保持它所有的候选者的引用。 69 | 70 | > 随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。 71 | 72 | > 一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理。 73 | 74 | 上一章:[第二十三章 烤羊肉串引来的思考 --- 命令模式]({{< relref "/docs/chapter23" >}}) 75 | 76 | 下一章:[第二十五章 世界需要和平 --- 中介者模式]({{< relref "/docs/chapter25" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter25.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十五章 世界需要和平 --- 中介者模式 3 | type: docs 4 | weight: 26 5 | --- 6 | 7 | ### 第二十五章 世界需要和平 --- 中介者模式 8 | 9 | ```php 10 | mediator = $mediator; 24 | } 25 | } 26 | 27 | class ConcreteMediator extends Mediator 28 | { 29 | private $colleague1; 30 | private $colleague2; 31 | 32 | public function setColleague1(Colleague $colleague) 33 | { 34 | $this->colleague1 = $colleague; 35 | } 36 | 37 | public function setColleague2(Colleague $colleague) 38 | { 39 | $this->colleague2 = $colleague; 40 | } 41 | 42 | public function send($message, Colleague $colleague) 43 | { 44 | if($this->colleague1 == $colleague) 45 | { 46 | $this->colleague2->notify($message); 47 | } else { 48 | $this->colleague1->notify($message); 49 | } 50 | } 51 | } 52 | 53 | class ConcreteColleague1 extends Colleague 54 | { 55 | public function send($message) 56 | { 57 | $this->mediator->send($message, $this); 58 | } 59 | 60 | public function notify($message) 61 | { 62 | echo "ConcreteColleague1 ".$message."\n"; 63 | } 64 | } 65 | 66 | class ConcreteColleague2 extends Colleague 67 | { 68 | public function send($message) 69 | { 70 | $this->mediator->send($message, $this); 71 | } 72 | 73 | public function notify($message) 74 | { 75 | echo "ConcreteColleague2 ".$message."\n";; 76 | } 77 | } 78 | 79 | //client 80 | 81 | $mediator = new ConcreteMediator(); 82 | $c1 = new ConcreteColleague1($mediator); 83 | $c2 = new ConcreteColleague2($mediator); 84 | 85 | $mediator->setColleague1($c1); 86 | $mediator->setColleague2($c2); 87 | 88 | $c1->send('do you eat?'); 89 | $c2->send('no, do you want to invite me to dinner?'); 90 | ``` 91 | 92 | 总结 93 | 94 | > ***中介者模式***,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互交互,从而使其耦合松散,而且可以独立地改变它们之间的交互。 95 | 96 | > 尽管将一个系统分割成许多对象通常可以增加其可复用性,但是对象间的交互连接的激增又会降低其可复用性了。 97 | 98 | > 大量的连接使得一个对象不大可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体,所以,对系统的行为进行任何较大的改动就十分困难了。 99 | 100 | > 中介者模式很容易在系统中应用,也很容易在系统中误用。当系统出现了‘多对多’交互复杂的对象群时,不要急于使用中介者模式,而要反思你的系统设计上是不是合理。 101 | 102 | > 由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统。 103 | 104 | > 中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的结合,以及想定制一个分布在多个类中的行为,而又不想生成太多的子类的场合。 105 | 106 | 上一章:[第二十四章 加薪非要老总批 --- 职责链模式]({{< relref "/docs/chapter24" >}}) 107 | 108 | 下一章:[第二十六章 项目多也别傻做 --- 享元模式]({{< relref "/docs/chapter26" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter26.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十六章 项目多也别傻做 --- 享元模式 3 | type: docs 4 | weight: 27 5 | --- 6 | 7 | ### 第二十六章 项目多也别傻做 --- 享元模式 8 | 9 | ```php 10 | class User 11 | { 12 | private $name; 13 | function __construct($name) 14 | { 15 | $this->name = $name; 16 | } 17 | 18 | public function getName() 19 | { 20 | return $this->name; 21 | } 22 | } 23 | 24 | abstract class WebSite 25 | { 26 | abstract public function use(User $user); 27 | } 28 | 29 | // 具体网站类 30 | class ConcreteWebSite extends WebSite 31 | { 32 | private $name = ''; 33 | 34 | function __construct($name) 35 | { 36 | $this->name = $name; 37 | } 38 | 39 | public function use(User $user) 40 | { 41 | echo "网站分类: ".$this->name."用户:".$user->getName()."\n"; 42 | } 43 | } 44 | 45 | //网站工厂 46 | class WebSiteFactory 47 | { 48 | private $flyweights = []; 49 | 50 | public function getWebSiteGategory($key) 51 | { 52 | if (empty($this->flyweights[$key])) { 53 | $this->flyweights[$key] = new ConcreteWebSite($key); 54 | } 55 | return $this->flyweights[$key]; 56 | } 57 | 58 | 59 | public function getWebSiteCount() 60 | { 61 | return count($this->flyweights); 62 | } 63 | } 64 | 65 | $f = new WebSiteFactory(); 66 | $fx = $f->getWebSiteGategory('产品展示'); 67 | $fx->use(new User('张伟')); 68 | 69 | $fy = $f->getWebSiteGategory('产品展示'); 70 | $fy->use(new User('王伟')); 71 | 72 | $fz = $f->getWebSiteGategory('产品展示'); 73 | $fz->use(new User('王芳')); 74 | 75 | $fl = $f->getWebSiteGategory('博客'); 76 | $fl->use(new User('李伟')); 77 | 78 | $fm = $f->getWebSiteGategory('博客'); 79 | $fm->use(new User('王秀英')); 80 | 81 | $fn = $f->getWebSiteGategory('博客'); 82 | $fn->use(new User('李秀英')); 83 | 84 | echo "网站分类总数:".$f->getWebSiteCount()."\n"; 85 | ``` 86 | 87 | 总结 88 | 89 | > ***享原模式*** 运用共享技术有效地支持大量细粒度的对象 90 | 91 | > 享原模式可以避免大量非常类似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。 92 | 93 | > 如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享原模式。 94 | 95 | 上一章:[第二十五章 世界需要和平 --- 中介者模式]({{< relref "/docs/chapter25" >}}) 96 | 97 | 下一章:[第二十七章 其实你不懂老板的心 --- 解释器模式]({{< relref "/docs/chapter27" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter27.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十七章 其实你不懂老板的心 --- 解释器模式 3 | type: docs 4 | weight: 28 5 | --- 6 | 7 | ### 第二十七章 其实你不懂老板的心 --- 解释器模式 8 | 9 | ```php 10 | input = $input; 39 | } 40 | 41 | public function getInput() 42 | { 43 | return $this->input; 44 | } 45 | 46 | private $output; 47 | public function setOutput($output) 48 | { 49 | $this->output = $output; 50 | } 51 | 52 | public function getOutput() 53 | { 54 | return $this->output; 55 | } 56 | } 57 | 58 | 59 | $context = new Context(); 60 | $syntax = []; 61 | array_push($syntax, new TerminalExpression()); 62 | array_push($syntax, new NonTerminalExpression()); 63 | array_push($syntax, new TerminalExpression()); 64 | array_push($syntax, new TerminalExpression()); 65 | 66 | foreach ($syntax as $value) { 67 | $value->interpret($context); 68 | } 69 | ``` 70 | 71 | > ***解释器模式***,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言的句子。 72 | 73 | > 如果一种特定语言类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。 74 | 75 | > 通常当有一个语言需要解释执行,并且你可将该语言的句子表示为一个抽象语法树时,可使用解释器模式。 76 | 77 | > 解释器模式容易修改和扩展文法,因为解释器模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。 78 | 79 | > 解释器模式不足的是要为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。 80 | 81 | 上一章:[第二十六章 项目多也别傻做 --- 享元模式]({{< relref "/docs/chapter26" >}}) 82 | 83 | 下一章:[第二十八章 男人和女人 --- 访问者模式]({{< relref "/docs/chapter28" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter28.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十八章 男人和女人 --- 访问者模式 3 | type: docs 4 | weight: 29 5 | --- 6 | 7 | ### 第二十八章 男人和女人 --- 访问者模式 8 | 9 | ```php 10 | getManConclusion($this); 68 | } 69 | } 70 | 71 | class Woman extends Person 72 | { 73 | public function accept(Action $visitor) 74 | { 75 | $visitor->getWomanConclusion($this); 76 | } 77 | } 78 | 79 | class ObjectStructure 80 | { 81 | private $person = []; 82 | 83 | public function acctch(Person $person) 84 | { 85 | array_push($this->person, $person); 86 | } 87 | 88 | public function display(Action $visitor) 89 | { 90 | foreach ($this->person as $person) { 91 | $person->accept($visitor); 92 | } 93 | } 94 | } 95 | 96 | 97 | $o = new ObjectStructure(); 98 | $o->acctch(new Man()); 99 | $o->acctch(new Woman()); 100 | 101 | // 成功时的反应 102 | $v1 = new Success(); 103 | $o->display($v1); 104 | 105 | 106 | $v2 = new Failing(); 107 | $o->display($v2); 108 | 109 | 110 | $v3 = new Amativeness(); 111 | $o->display($v3); 112 | ``` 113 | 114 | 总结 115 | 116 | > ***访问者模式***,表示一个作用于某对象结构中的各个元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 117 | 118 | > 访问者模式适合用于数据结构相对稳定的系统。它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。 119 | 120 | > 访问者的目的是要把处理从数据结构分离出来。这样系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。 121 | 122 | > 增加新的操作容易,因为增加新的操作就意味着增加一个新的访问者。访问者将有关行为集中到一个访问者对象中。 123 | 124 | > 访问者模式使增加新的数据结构变得困难了。 125 | 126 | 127 | 128 | 129 | 上一章:[第二十七章 其实你不懂老板的心 --- 解释器模式]({{< relref "/docs/chapter27" >}}) 130 | 131 | 下一章:[第二十九章 OOTV杯超级模式大赛 --- 模式总结]({{< relref "/docs/chapter29" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter29.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第二十九章 OOTV杯超级模式大赛 --- 模式总结 3 | type: docs 4 | weight: 30 5 | --- 6 | 7 | ### 第二十九章 OOTV杯超级模式大赛 --- 模式总结 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 | 上一章:[第二十八章 男人和女人 --- 访问者模式]({{< relref "/docs/chapter28" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第三章 拍摄UFO --- 单一职责原则 3 | type: docs 4 | weight: 4 5 | --- 6 | 7 | ### 第三章 拍摄UFO --- 单一职责原则 8 | 9 | 总结 10 | 11 | > ***单一职责原则***, 就一个类而言,应该仅有一个引起 它变化的原因。 12 | 13 | >如果一个类承担的职责过多,就等于把职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破环。 14 | 15 | >软件设计真正要做的许多内容,就是发现职责并把这些职责相互分离。 16 | 17 | > 如果你能够想到多于一个的动机改变一个类,那么这个类就具有多于一个类的职责。 18 | 19 | 上一章:[第二章 商场促销 --- 策略模式]({{< relref "/docs/chapter2" >}}) 20 | 21 | 下一章:[第四章 考研求职两不误 --- 开放-封闭原则]({{< relref "/docs/chapter4" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter4.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第四章 研求职两不误 --- 开放-封闭原则 3 | type: docs 4 | weight: 5 5 | --- 6 | 7 | ### 第四章 研求职两不误 --- 开放-封闭原则 8 | 9 | 总结 10 | > ***开放-封闭原则***, 是说软件实体应该可以扩展,但是不可以修改。 11 | 12 | > 怎样的设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本呢? 13 | 14 | > 无论模块是多么的‘封闭’,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。 15 | 16 | > 等到发生变化时立即采取行动。 17 | 18 | > 在我们最初编写代码时,假设变化不会发生。当发生变化时,我们就创建抽象来隔离以后发生的同类变化。 19 | 20 | > 面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。 21 | 22 | > 开发-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护,可复用,灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一件好事。拒绝不成熟的抽象和抽象本身一样重要。 23 | 24 | 25 | 26 | 上一章:[第三章 拍摄UFO --- 单一职责原则]({{< relref "/docs/chapter3" >}}) 27 | 28 | 下一章:[第五章 会修电脑不会修收音机? --- 依赖倒转原则]({{< relref "/docs/chapter5" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter5.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第五章 会修电脑不会修收音机? --- 依赖倒转原则 3 | type: docs 4 | weight: 6 5 | --- 6 | 7 | ### 第五章 会修电脑不会修收音机? --- 依赖倒转原则 8 | 9 | 总结 10 | > ***依赖倒转原则***, 高层模块不应该依赖底层模块,抽象不应该依赖细节,都应该依赖抽象。针对接口编程,不要对实现编程。 11 | 12 | > ***里氏替换原则***,子类型必须能够替换它们的父类型。 13 | 14 | > 只有当子类可以替换父类,软件单位的功能不受影响时,父类才真正被复用,而子类也能够在父类的基础上增加新的行为。 15 | 16 | > 由于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展。 17 | 18 | > 依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。 19 | 20 | 上一章:[第四章 研求职两不误 --- 开放-封闭原则]({{< relref "/docs/chapter4" >}}) 21 | 22 | 下一章:[第六章 穿什么有这么重要吗 --- 装饰模式]({{< relref "/docs/chapter6" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter7.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第七章 为别人做嫁衣 --- 代理模式 3 | type: docs 4 | weight: 8 5 | --- 6 | 7 | ### 第七章 为别人做嫁衣 --- 代理模式 8 | 9 | ```php 10 | name = $name; 19 | } 20 | 21 | public function getName() 22 | { 23 | return $this->name; 24 | } 25 | } 26 | 27 | // 代理接口 28 | interface GiveGift 29 | { 30 | public function GiveDolls(); 31 | public function GiveFlowers(); 32 | public function GiveChocolate(); 33 | } 34 | 35 | // 代理实现送礼物接口 36 | class Proxy implements GiveGift 37 | { 38 | protected $pursuit; 39 | 40 | function __construct(SchoolGirl $girl) 41 | { 42 | $this->pursuit = new Pursuit($girl); 43 | } 44 | 45 | public function GiveDolls() 46 | { 47 | $this->pursuit->GiveDolls(); 48 | } 49 | 50 | public function GiveFlowers() 51 | { 52 | $this->pursuit->GiveFlowers(); 53 | } 54 | 55 | public function GiveChocolate() 56 | { 57 | $this->pursuit->GiveChocolate(); 58 | } 59 | } 60 | 61 | // 追求者类实现送礼物接口 62 | class Pursuit implements GiveGift 63 | { 64 | protected $girl; 65 | function __construct(SchoolGirl $girl) 66 | { 67 | $this->girl = $girl; 68 | } 69 | 70 | public function GiveDolls() 71 | { 72 | echo $this->girl->getName()." 送你娃娃\n"; 73 | } 74 | 75 | public function GiveFlowers() 76 | { 77 | echo $this->girl->getName()." 送你花\n"; 78 | } 79 | 80 | public function GiveChocolate() 81 | { 82 | echo $this->girl->getName()." 送你巧克力\n"; 83 | } 84 | } 85 | 86 | // 客户端代码 87 | $girl = new SchoolGirl('李梅'); 88 | $proxy = new Proxy($girl); 89 | $proxy->GiveDolls(); 90 | $proxy->GiveChocolate(); 91 | $proxy->GiveFlowers(); 92 | 93 | ``` 94 | 95 | 总结: 96 | > ***代理模式***,为其他对象提供一种代理以控制对这个对象的访问 97 | 98 | 上一章:[第六章 穿什么有这么重要吗 --- 装饰模式]({{< relref "/docs/chapter6" >}}) 99 | 100 | 下一章:[第八章 雷锋依然在人间 --- 工厂方法模式]({{< relref "/docs/chapter8" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter8.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第八章 雷锋依然在人间 --- 工厂方法模式 3 | type: docs 4 | weight: 9 5 | --- 6 | 7 | ### 第八章 雷锋依然在人间 --- 工厂方法模式 8 | 9 | 根据[第一章](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter1.md),简单工厂模式(加减乘除)是这样的: 10 | ```php 11 | class OperationFactory 12 | { 13 | public static function createOperation($operation) 14 | { 15 | switch ($operation) { 16 | case '+': 17 | $oper = new OperationAdd(); 18 | break; 19 | case '-': 20 | $oper = new OperationSub(); 21 | break; 22 | case '/': 23 | $oper = new OperationDiv(); 24 | break; 25 | case '*': 26 | $oper = new OperationMul(); 27 | break; 28 | } 29 | return $oper; 30 | } 31 | } 32 | // 客户端代码 33 | $operation = OperationFactory::createOperation('+'); 34 | $operation->setA(1); 35 | $operation->setA(2); 36 | echo $operation->getResult()."\n"; 37 | ``` 38 | 换成工厂方法模式 39 | ```php 40 | interface IFactory 41 | { 42 | public function CreateOperation(); 43 | } 44 | 45 | class AddFactory implements IFactory 46 | { 47 | public function CreateOperation() 48 | { 49 | return new OperationAdd(); 50 | } 51 | } 52 | 53 | class SubFactory implements IFactory 54 | { 55 | public function CreateOperation() 56 | { 57 | return new OperationSub(); 58 | } 59 | } 60 | 61 | class MulFactory implements IFactory 62 | { 63 | public function CreateOperation() 64 | { 65 | return new OperationMul(); 66 | } 67 | } 68 | 69 | class DivFactory implements IFactory 70 | { 71 | public function CreateOperation() 72 | { 73 | return new OperationDiv(); 74 | } 75 | } 76 | 77 | //客户端代码 78 | $operationFactory = new AddFactory(); 79 | $operation = $operationFactory->CreateOperation(); 80 | $operation->setA(10); 81 | $operation->setB(10); 82 | echo $operation->getResult()."\n"; 83 | ``` 84 | 85 | 86 | 总结: 87 | 88 | > ***工厂方法模式***,定义一个创建对象的接口,让子类确定实例化哪一个类。工厂方法使一个类的实例化延迟到7其子类。 89 | 90 | > 简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据用户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。 91 | 92 | > 工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。你 想要加功能,本来是改工厂类的,而现在是修改客户端。 93 | 94 | 上一章:[第七章 为别人做嫁衣 --- 代理模式]({{< relref "/docs/chapter7" >}}) 95 | 96 | 下一章:[第九章 简历复印 --- 原型模式]({{< relref "/docs/chapter9" >}}) -------------------------------------------------------------------------------- /book/content/docs/chapter9.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 第九章 简历复印 --- 原型模式 3 | type: docs 4 | weight: 10 5 | --- 6 | 7 | ### 第九章 简历复印 --- 原型模式 8 | 9 | ```php 10 | company = $name; 19 | } 20 | 21 | public function getName() 22 | { 23 | return $this->company; 24 | } 25 | } 26 | 27 | class Resume 28 | { 29 | private $name; 30 | private $sex; 31 | private $age; 32 | private $timeArea; 33 | private $company; 34 | 35 | function __construct($name) 36 | { 37 | $this->name = $name; 38 | $this->company = new Company(); 39 | } 40 | 41 | public function setPersonalInfo($sex, $age) 42 | { 43 | $this->sex = $sex; 44 | $this->age = $age; 45 | } 46 | 47 | public function setWorkExperience($timeArea, $company) 48 | { 49 | $this->timeArea = $timeArea; 50 | $this->company->setName($company); 51 | } 52 | 53 | public function display() 54 | { 55 | echo $this->name." ".$this->sex." ".$this->age."\n"; 56 | echo $this->timeArea." ".$this->company->getName()."\n"; 57 | } 58 | 59 | // 对引用执行深复制 60 | function __clone() 61 | { 62 | $this->company = clone $this->company; 63 | } 64 | } 65 | 66 | // 客户端代码 67 | $resume = new Resume("大鸟"); 68 | $resume->setPersonalInfo("男", 29); 69 | $resume->setWorkExperience("1998-2000","xxx 公司"); 70 | 71 | $resume2 = clone $resume; 72 | $resume2->setPersonalInfo("男", 40); 73 | $resume2->setWorkExperience("1998-2010","xx 公司"); 74 | 75 | $resume->display(); 76 | $resume2->display(); 77 | 78 | ``` 79 | 80 | 总结: 81 | 82 | > ***原型模式***,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 83 | 84 | > 原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。 85 | 86 | > 一般在初始化的信息不发生变化的情况下,克隆是最好的办法。既隐藏了对象创建的细节,又对性能是大大的提高。 87 | 88 | 89 | 上一章:[第八章 雷锋依然在人间 --- 工厂方法模式]({{< relref "/docs/chapter8" >}}) 90 | 91 | 下一章:[第十章 考题抄错会做也白搭 --- 模版方法模式]({{< relref "/docs/chapter10" >}}) -------------------------------------------------------------------------------- /book/content/docs/序言.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 序言 3 | type: docs 4 | weight: 1 5 | --- 6 | 7 | [《大话设计模式》](https://book.douban.com/subject/2334288/)php版本 8 | 用自己现在用的语言重新写一遍,文中的代码均可以在终端内执行 9 | 10 | 相关资源: 11 | 12 | [Design Patterns for Humans](https://github.com/kamranahmedse/design-patterns-for-humans) 13 | 14 | [DesignPatternsPHP](https://github.com/domnikl/DesignPatternsPHP) 15 | ## 目录 16 | 17 | - [第一章 代码无错就是优 ---简单工厂模式]({{< relref "/docs/chapter1" >}}) 18 | 19 | - [第二章 商场促销 --- 策略模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter2.md) 20 | 21 | - [第三章 拍摄UFO --- 单一职责原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter3.md) 22 | 23 | - [第四章 研求职两不误 --- 开放-封闭原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter4.md) 24 | 25 | - [第五章 会修电脑不会修收音机? --- 依赖倒转原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter5.md) 26 | 27 | - [第六章 穿什么有这么重要吗 --- 装饰模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter6.md) 28 | 29 | - [第七章 为别人做嫁衣 --- 代理模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter7.md) 30 | 31 | - [第八章 雷锋依然在人间 --- 工厂方法模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter8.md) 32 | 33 | - [第九章 简历复印 --- 原型模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter9.md) 34 | 35 | - [第十章 考题抄错会做也白搭 --- 模版方法模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter10.md) 36 | 37 | - [第十一章 无熟人难办事 --- 迪米特法则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter11.md) 38 | 39 | - [第十二章 牛市股票还会亏钱 --- 外观模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter12.md) 40 | 41 | - [第十三章 好菜每回味不同 --- 建造者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter13.md) 42 | 43 | - [第十四章 老板回来,我不知道 --- 观察者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter14.md) 44 | 45 | - [第十五章 就不能不换DB吗? --- 抽象工厂模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter15.md) 46 | 47 | - [第十六章 无尽加班何时休 --- 状态模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter16.md) 48 | 49 | - [第十七章 在NBA我需要翻译 --- 适配器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter17.md) 50 | 51 | - [第十八章 如果再回到从前 --- 备忘录模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter18.md) 52 | 53 | - [第十九章 分公司 = 一部分 --- 组合模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter19.md) 54 | 55 | - [第二十章 想走?可以!先买票 --- 迭代器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter20.md) 56 | 57 | - [第二十一章 有些类也需要计划生育 --- 单例模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter21.md) 58 | 59 | - [第二十二章 手机软件何时统一 --- 桥接模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter22.md) 60 | 61 | - [第二十三章 烤羊肉串引来的思考 --- 命令模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter23.md) 62 | 63 | - [第二十四章 加薪非要老总批 --- 职责链模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter24.md) 64 | 65 | - [第二十五章 世界需要和平 --- 中介者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter25.md) 66 | 67 | - [第二十六章 项目多也别傻做 --- 享元模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter26.md) 68 | 69 | - [第二十七章 其实你不懂老板的心 --- 解释器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter27.md) 70 | 71 | - [第二十八章 男人和女人 --- 访问者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter28.md) 72 | 73 | - [第二十九章 OOTV杯超级模式大赛 --- 模式总结](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter29.md) 74 | 75 | 76 | ## License 77 | 78 | The MIT License. 79 | -------------------------------------------------------------------------------- /book/public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 404 Page not found | design-patterns-by-php 14 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 35 | 36 | 37 | 38 |
39 |
40 |

404

41 |

Page Not Found

42 |

43 | design-patterns-by-php 44 |

45 |
46 |
47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /book/public/categories/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Categories on design-patterns-by-php 5 | https://design-patterns-by-php.hulin.ink/categories/ 6 | Recent content in Categories on design-patterns-by-php 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /book/public/en.search.min.9e32b36e065fcc0a76dade0cc47798d1533be64df6d2282bd5b4fb040caf152d.js: -------------------------------------------------------------------------------- 1 | 'use strict';(function(){const input=document.querySelector('#book-search-input');const results=document.querySelector('#book-search-results');if(!input){return} 2 | input.addEventListener('focus',init);input.addEventListener('keyup',search);document.addEventListener('keypress',focusSearchFieldOnKeyPress);function focusSearchFieldOnKeyPress(event){if(input===document.activeElement){return;} 3 | const characterPressed=String.fromCharCode(event.charCode);if(!isHotkey(characterPressed)){return;} 4 | input.focus();event.preventDefault();} 5 | function isHotkey(character){const dataHotkeys=input.getAttribute('data-hotkeys')||'';return dataHotkeys.indexOf(character)>=0;} 6 | function init(){input.removeEventListener('focus',init);input.required=true;loadScript('/flexsearch.min.js');loadScript('/en.search-data.min.527444053051030881c267eb7bed3324c34112619e4bd7041755fd3ff22e337e.js',function(){input.required=false;search();});} 7 | function search(){while(results.firstChild){results.removeChild(results.firstChild);} 8 | if(!input.value){return;} 9 | const searchHits=window.bookSearchIndex.search(input.value,10);searchHits.forEach(function(page){const li=element('
  • ');const a=li.querySelector('a'),small=li.querySelector('small');a.href=page.href;a.textContent=page.title;small.textContent=page.section;results.appendChild(li);});} 10 | function loadScript(src,callback){const script=document.createElement('script');script.defer=true;script.async=false;script.src=src;script.onload=callback;document.head.appendChild(script);} 11 | function element(content){const div=document.createElement('div');div.innerHTML=content;return div.firstChild;}})(); -------------------------------------------------------------------------------- /book/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/favicon.png -------------------------------------------------------------------------------- /book/public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /book/public/fonts/roboto-mono-v6-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/fonts/roboto-mono-v6-latin-regular.woff -------------------------------------------------------------------------------- /book/public/fonts/roboto-mono-v6-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/fonts/roboto-mono-v6-latin-regular.woff2 -------------------------------------------------------------------------------- /book/public/fonts/roboto-v19-latin-300italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/fonts/roboto-v19-latin-300italic.woff -------------------------------------------------------------------------------- /book/public/fonts/roboto-v19-latin-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/fonts/roboto-v19-latin-300italic.woff2 -------------------------------------------------------------------------------- /book/public/fonts/roboto-v19-latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/fonts/roboto-v19-latin-700.woff -------------------------------------------------------------------------------- /book/public/fonts/roboto-v19-latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/fonts/roboto-v19-latin-700.woff2 -------------------------------------------------------------------------------- /book/public/fonts/roboto-v19-latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/fonts/roboto-v19-latin-regular.woff -------------------------------------------------------------------------------- /book/public/fonts/roboto-v19-latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/book/public/fonts/roboto-v19-latin-regular.woff2 -------------------------------------------------------------------------------- /book/public/katex/auto-render.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,function(e){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([function(t,r){t.exports=e},function(e,t,r){"use strict";r.r(t);var n=r(0),o=r.n(n),a=function(e,t,r){for(var n=r,o=0,a=e.length;n 2 | 4 | 5 | 6 | https://design-patterns-by-php.hulin.ink/docs/%E5%BA%8F%E8%A8%80/ 7 | 8 | 9 | 10 | https://design-patterns-by-php.hulin.ink/docs/chapter1/ 11 | 12 | 13 | 14 | https://design-patterns-by-php.hulin.ink/docs/chapter2/ 15 | 16 | 17 | 18 | https://design-patterns-by-php.hulin.ink/docs/chapter3/ 19 | 20 | 21 | 22 | https://design-patterns-by-php.hulin.ink/docs/chapter4/ 23 | 24 | 25 | 26 | https://design-patterns-by-php.hulin.ink/docs/chapter5/ 27 | 28 | 29 | 30 | https://design-patterns-by-php.hulin.ink/docs/chapter6/ 31 | 32 | 33 | 34 | https://design-patterns-by-php.hulin.ink/docs/chapter7/ 35 | 36 | 37 | 38 | https://design-patterns-by-php.hulin.ink/docs/chapter8/ 39 | 40 | 41 | 42 | https://design-patterns-by-php.hulin.ink/docs/chapter9/ 43 | 44 | 45 | 46 | https://design-patterns-by-php.hulin.ink/docs/chapter10/ 47 | 48 | 49 | 50 | https://design-patterns-by-php.hulin.ink/docs/chapter11/ 51 | 52 | 53 | 54 | https://design-patterns-by-php.hulin.ink/docs/chapter12/ 55 | 56 | 57 | 58 | https://design-patterns-by-php.hulin.ink/docs/chapter13/ 59 | 60 | 61 | 62 | https://design-patterns-by-php.hulin.ink/docs/chapter14/ 63 | 64 | 65 | 66 | https://design-patterns-by-php.hulin.ink/docs/chapter15/ 67 | 68 | 69 | 70 | https://design-patterns-by-php.hulin.ink/docs/chapter16/ 71 | 72 | 73 | 74 | https://design-patterns-by-php.hulin.ink/docs/chapter17/ 75 | 76 | 77 | 78 | https://design-patterns-by-php.hulin.ink/docs/chapter18/ 79 | 80 | 81 | 82 | https://design-patterns-by-php.hulin.ink/docs/chapter19/ 83 | 84 | 85 | 86 | https://design-patterns-by-php.hulin.ink/docs/chapter20/ 87 | 88 | 89 | 90 | https://design-patterns-by-php.hulin.ink/docs/chapter21/ 91 | 92 | 93 | 94 | https://design-patterns-by-php.hulin.ink/docs/chapter22/ 95 | 96 | 97 | 98 | https://design-patterns-by-php.hulin.ink/docs/chapter23/ 99 | 100 | 101 | 102 | https://design-patterns-by-php.hulin.ink/docs/chapter24/ 103 | 104 | 105 | 106 | https://design-patterns-by-php.hulin.ink/docs/chapter25/ 107 | 108 | 109 | 110 | https://design-patterns-by-php.hulin.ink/docs/chapter26/ 111 | 112 | 113 | 114 | https://design-patterns-by-php.hulin.ink/docs/chapter27/ 115 | 116 | 117 | 118 | https://design-patterns-by-php.hulin.ink/docs/chapter28/ 119 | 120 | 121 | 122 | https://design-patterns-by-php.hulin.ink/docs/chapter29/ 123 | 124 | 125 | 126 | https://design-patterns-by-php.hulin.ink/categories/ 127 | 128 | 129 | 130 | https://design-patterns-by-php.hulin.ink/docs/ 131 | 132 | 133 | 134 | https://design-patterns-by-php.hulin.ink/tags/ 135 | 136 | 137 | 138 | https://design-patterns-by-php.hulin.ink/ 139 | 140 | 141 | -------------------------------------------------------------------------------- /book/public/svg/calendar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /book/public/svg/edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /book/public/svg/menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /book/public/svg/toc.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /book/public/svg/translate.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /book/public/tags/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Tags on design-patterns-by-php 5 | https://design-patterns-by-php.hulin.ink/tags/ 6 | Recent content in Tags on design-patterns-by-php 7 | Hugo -- gohugo.io 8 | en-us 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /book/resources/_gen/assets/scss/book.scss_50fc8c04e12a2f59027287995557ceff.json: -------------------------------------------------------------------------------- 1 | {"Target":"book.min.134b70e5316650a530cb42e4e8630b2a01d532bebfc0337028211175336e4806.css","MediaType":"text/css","Data":{"Integrity":"sha256-E0tw5TFmUKUwy0Lk6GMLKgHVMr6/wDNwKCERdTNuSAY="}} -------------------------------------------------------------------------------- /codes/AbstractFactory.php: -------------------------------------------------------------------------------- 1 | id = $id; 11 | } 12 | 13 | public function getId($id) 14 | { 15 | return $this->id; 16 | } 17 | 18 | private $name = null; 19 | public function setName($name) 20 | { 21 | $this->name = $name; 22 | } 23 | 24 | public function getName($name) 25 | { 26 | return $this->id; 27 | } 28 | } 29 | 30 | class Department 31 | { 32 | private $id = null; 33 | public function setId($id) 34 | { 35 | $this->id = $id; 36 | } 37 | 38 | public function getId($id) 39 | { 40 | return $this->id; 41 | } 42 | 43 | private $name = null; 44 | public function setName($name) 45 | { 46 | $this->name = $name; 47 | } 48 | 49 | public function getName($name) 50 | { 51 | return $this->id; 52 | } 53 | } 54 | 55 | interface IUser 56 | { 57 | public function insert(User $user); 58 | public function getUser($id); 59 | } 60 | 61 | class SqlserverUser implements IUser 62 | { 63 | public function insert(User $user) 64 | { 65 | echo "往SQL Server中的User表添加一条记录\n"; 66 | } 67 | 68 | public function getUser($id) 69 | { 70 | echo "根据id得到SQL Server中User表一条记录\n"; 71 | } 72 | } 73 | 74 | class AcessUser implements IUser 75 | { 76 | public function insert(User $user) 77 | { 78 | echo "往Acess Server中的User表添加一条记录\n"; 79 | } 80 | 81 | public function getUser($id) 82 | { 83 | echo "根据id得到Acess Server中User表一条记录\n"; 84 | } 85 | } 86 | 87 | // interface IFactory 88 | // { 89 | // public function CreateUser(); 90 | // public function CreateDepartment(); 91 | // } 92 | 93 | // class SqlserverFactory implements IFactory 94 | // { 95 | // public function CreateUser() 96 | // { 97 | // return new SqlserverUser(); 98 | // } 99 | 100 | // public function CreateDepartment() 101 | // { 102 | // return new SqlserverDepartment(); 103 | // } 104 | // } 105 | 106 | // class AcessFactory implements IFactory 107 | // { 108 | // public function CreateUser() 109 | // { 110 | // return new AcessUser(); 111 | // } 112 | 113 | // public function CreateDepartment() 114 | // { 115 | // return new AcessDepartment(); 116 | // } 117 | // } 118 | //简单工厂替换抽象工厂 119 | class DataBase 120 | { 121 | const DB = 'Sqlserver'; 122 | // private $db = 'Access'; 123 | 124 | public static function CreateUser() 125 | { 126 | $class = static::DB.'User'; 127 | return new $class(); 128 | } 129 | 130 | public static function CreateDepartment() 131 | { 132 | $class = static::DB.'Department'; 133 | return new $class(); 134 | } 135 | 136 | } 137 | 138 | 139 | interface IDepartment 140 | { 141 | public function insert(Department $user); 142 | public function getDepartment($id); 143 | } 144 | 145 | class SqlserverDepartment implements IDepartment 146 | { 147 | public function insert(Department $department) 148 | { 149 | echo "往SQL Server中的Department表添加一条记录\n"; 150 | } 151 | 152 | public function getDepartment($id) 153 | { 154 | echo "根据id得到SQL Server中Department表一条记录\n"; 155 | } 156 | } 157 | 158 | class AcessDepartment implements IDepartment 159 | { 160 | public function insert(Department $department) 161 | { 162 | echo "往Acess Server中的Department表添加一条记录\n"; 163 | } 164 | 165 | public function getDepartment($id) 166 | { 167 | echo "根据id得到Acess Server中Department表一条记录\n"; 168 | } 169 | } 170 | 171 | //客户端代码 172 | // $user = new User(); 173 | // $iu = (new AcessFactory())->CreateUser(); 174 | // $iu->insert($user); 175 | // $iu->getUser(1); 176 | 177 | // $department = new Department(); 178 | // $id = (new AcessFactory())->CreateDepartment(); 179 | // $id->insert($department); 180 | // $id->getDepartment(1); 181 | ///////////////////////////////////////////////// 182 | 183 | //改为简单工厂后的客户端代码 184 | $user = new User(); 185 | $iu = DataBase::CreateUser(); 186 | $iu->insert($user); 187 | $iu->getUser(1); 188 | 189 | $department = new Department(); 190 | $id = DataBase::CreateDepartment(); 191 | $id->insert($department); 192 | $id->getDepartment(1); 193 | 194 | -------------------------------------------------------------------------------- /codes/Adapter.php: -------------------------------------------------------------------------------- 1 | name = $name; 11 | } 12 | 13 | abstract public function Attack(); 14 | abstract public function Defense(); 15 | } 16 | 17 | //前锋 18 | class Forwards extends Player 19 | { 20 | public function Attack() 21 | { 22 | echo "前锋:".$this->name." 进攻\n"; 23 | } 24 | public function Defense() 25 | { 26 | echo "前锋:".$this->name." 防守\n"; 27 | } 28 | } 29 | 30 | //中锋 31 | class Center extends Player 32 | { 33 | function __construct() 34 | { 35 | parent::__construct(); 36 | } 37 | 38 | public function Attack() 39 | { 40 | echo "中锋:".$this->name." 进攻\n"; 41 | } 42 | public function Defense() 43 | { 44 | echo "中锋:".$this->name." 防守\n"; 45 | } 46 | } 47 | 48 | //外籍中锋 49 | class ForeignCenter 50 | { 51 | private $name; 52 | public function setName($name) 53 | { 54 | $this->name = $name; 55 | } 56 | 57 | public function getName() 58 | { 59 | return $this->name; 60 | } 61 | 62 | public function 进攻() 63 | { 64 | echo "外籍中锋:".$this->name." 进攻\n"; 65 | } 66 | 67 | public function 防守() 68 | { 69 | echo "外籍中锋:".$this->name." 防守\n"; 70 | } 71 | } 72 | 73 | //翻译者 74 | class Translator extends Player 75 | { 76 | private $foreignCenter; 77 | 78 | function __construct($name) 79 | { 80 | $this->foreignCenter = new ForeignCenter(); 81 | $this->foreignCenter->setName($name); 82 | } 83 | 84 | public function Attack() 85 | { 86 | $this->foreignCenter->进攻(); 87 | } 88 | public function Defense() 89 | { 90 | $this->foreignCenter->防守(); 91 | } 92 | 93 | } 94 | 95 | 96 | 97 | // 客户端代码 98 | $forwards = new Forwards("巴蒂尔"); 99 | $forwards->Attack(); 100 | $forwards->Defense(); 101 | 102 | $translator = new Translator("姚明"); 103 | $translator->Attack(); 104 | $translator->Defense(); 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /codes/Bridge.php: -------------------------------------------------------------------------------- 1 | soft = $soft; 37 | } 38 | 39 | //运行 40 | abstract public function run(); 41 | } 42 | 43 | // 手机品牌n 44 | class HandsetBrandN extends HandsetBrand 45 | { 46 | public function run() 47 | { 48 | $this->soft->run(); 49 | } 50 | } 51 | 52 | // 手机品牌m 53 | class HandsetBrandM extends HandsetBrand 54 | { 55 | public function run() 56 | { 57 | $this->soft->run(); 58 | } 59 | } 60 | 61 | //客户端调用代码 62 | $ab = new HandsetBrandN(); 63 | $ab->setHandsetSoft(new HandsetGame()); 64 | $ab->run(); 65 | 66 | $ab->setHandsetSoft(new HandsetAddressList()); 67 | $ab->run(); 68 | 69 | $ab = new HandsetBrandM(); 70 | $ab->setHandsetSoft(new HandsetGame()); 71 | $ab->run(); 72 | 73 | $ab->setHandsetSoft(new HandsetAddressList()); 74 | $ab->run(); 75 | -------------------------------------------------------------------------------- /codes/Builder.php: -------------------------------------------------------------------------------- 1 | personBuilder = $personBuilder; 87 | } 88 | 89 | public function CreatePerson() 90 | { 91 | $this->personBuilder->BuildHead(); 92 | $this->personBuilder->BuildBody(); 93 | $this->personBuilder->BuildArmRight(); 94 | $this->personBuilder->BuildArmLeft(); 95 | $this->personBuilder->BuildLegLeft(); 96 | $this->personBuilder->BuildLegRight(); 97 | } 98 | } 99 | 100 | 101 | //客户端代码 102 | 103 | echo "苗条的:\n"; 104 | $thinDirector = new PersonDirector(new PersonThinBuilder()); 105 | $thinDirector->CreatePerson(); 106 | 107 | echo "\n胖的:\n"; 108 | $fatDirector = new PersonDirector(new PersonFatBuilder()); 109 | $fatDirector->CreatePerson(); 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /codes/Clone.php: -------------------------------------------------------------------------------- 1 | company = $name; 10 | } 11 | 12 | public function getName() 13 | { 14 | return $this->company; 15 | } 16 | } 17 | 18 | class Resume 19 | { 20 | private $name; 21 | private $sex; 22 | private $age; 23 | private $timeArea; 24 | private $company; 25 | 26 | function __construct($name) 27 | { 28 | $this->name = $name; 29 | $this->company = new Company(); 30 | } 31 | 32 | public function setPersonalInfo($sex, $age) 33 | { 34 | $this->sex = $sex; 35 | $this->age = $age; 36 | } 37 | 38 | public function setWorkExperience($timeArea, $company) 39 | { 40 | $this->timeArea = $timeArea; 41 | $this->company->setName($company); 42 | } 43 | 44 | public function display() 45 | { 46 | echo $this->name." ".$this->sex." ".$this->age."\n"; 47 | echo $this->timeArea." ".$this->company->getName()."\n"; 48 | } 49 | 50 | // 对引用执行深复制 51 | function __clone() 52 | { 53 | $this->company = clone $this->company; 54 | } 55 | } 56 | 57 | // 客户端代码 58 | $resume = new Resume("大鸟"); 59 | $resume->setPersonalInfo("男", 29); 60 | $resume->setWorkExperience("1998-2000","xxx 公司"); 61 | 62 | $resume2 = clone $resume; 63 | $resume2->setPersonalInfo("男", 40); 64 | $resume2->setWorkExperience("1998-2010","xx 公司"); 65 | 66 | $resume->display(); 67 | $resume2->display(); 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /codes/Command.php: -------------------------------------------------------------------------------- 1 | receiver = $receiver; 26 | } 27 | 28 | abstract public function excuteCommand(); 29 | } 30 | 31 | //烤羊肉 32 | class BakeMuttonCommand extends Command 33 | { 34 | public function excuteCommand() 35 | { 36 | $this->receiver->bakeMutton(); 37 | } 38 | } 39 | 40 | //烤鸡翅 41 | class BakeChickenWingCommand extends Command 42 | { 43 | public function excuteCommand() 44 | { 45 | $this->receiver->bakeChickenWing(); 46 | } 47 | } 48 | 49 | //服务员 50 | class Waiter 51 | { 52 | private $commands = []; 53 | 54 | //设置订单 55 | public function setOrder(Command $command) 56 | { 57 | if ($command instanceof BakeChickenWingCommand) 58 | { 59 | echo "服务员: 鸡翅没有了,请点别的烧烤\n"; 60 | } else { 61 | echo "增加订单\n"; 62 | array_push($this->commands, $command); 63 | } 64 | } 65 | 66 | //取消订单 67 | public function cancelOrder(Command $command){} 68 | 69 | //通知执行 70 | public function notify() 71 | { 72 | foreach ($this->commands as $value) { 73 | $value->excuteCommand(); 74 | } 75 | } 76 | } 77 | 78 | //客户端代码 79 | 80 | //开店前准备 81 | $boy = new Barbecuer(); 82 | $bakeMuttonCommand1 = new BakeMuttonCommand($boy); 83 | $bakeMuttonCommand2 = new BakeMuttonCommand($boy); 84 | $bakeChickenWingCommand1 = new BakeChickenWingCommand($boy); 85 | $girl = new Waiter(); 86 | 87 | //开门营业 88 | $girl->setOrder($bakeMuttonCommand1); 89 | $girl->setOrder($bakeMuttonCommand2); 90 | $girl->setOrder($bakeChickenWingCommand1); 91 | $girl->notify(); 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /codes/Composite.php: -------------------------------------------------------------------------------- 1 | name = $name; 11 | } 12 | 13 | //通常用add和remove方法来提供增加或移除树枝货树叶的功能 14 | abstract public function add(Component $c); 15 | abstract public function remove(Component $c); 16 | abstract public function display($depth); 17 | } 18 | 19 | //leaf在组合中表示叶节点对象,叶节点对象没有子节点。 20 | class Leaf extends Component 21 | { 22 | // 由于叶子没有再增加分枝和树叶,所以add和remove方法实现它没有意义, 23 | // 但这样做可以消除叶节点和枝节点对象在抽象层次的区别,它们具有完全一致的接口 24 | public function add(Component $c) 25 | { 26 | echo "can not add to a leaf\n"; 27 | } 28 | 29 | public function remove(Component $c) 30 | { 31 | echo "can not remove to a leaf\n"; 32 | } 33 | 34 | // 叶节点的具体方法,此处是显示其名称和级别 35 | public function display($depth) 36 | { 37 | echo str_repeat('-', $depth).$this->name."\n"; 38 | } 39 | } 40 | 41 | //composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加add和删除remove. 42 | 43 | class Composite extends Component 44 | { 45 | //一个子对象集合用来存储其下属的枝节点和叶节点。 46 | private $childern = []; 47 | 48 | public function add(Component $c) 49 | { 50 | array_push($this->childern, $c); 51 | } 52 | 53 | public function remove(Component $c) 54 | { 55 | foreach ($this->childern as $key => $value) { 56 | if ($c === $value) { 57 | unset($this->childern[$key]); 58 | } 59 | } 60 | } 61 | 62 | // 显示其枝节点名称,并对其下级进行遍历 63 | public function display($depth) 64 | { 65 | echo str_repeat('-', $depth).$this->name."\n"; 66 | foreach ($this->childern as $component) { 67 | $component->display($depth + 2); 68 | } 69 | } 70 | } 71 | 72 | //客户端代码 73 | 74 | $root = new Composite('root'); 75 | $root->add(new Leaf("Leaf A")); 76 | $root->add(new Leaf("Leaf B")); 77 | 78 | $comp = new Composite("Composite X"); 79 | $comp->add(new Leaf("Leaf XA")); 80 | $comp->add(new Leaf("Leaf XB")); 81 | 82 | $root->add($comp); 83 | 84 | $comp2 = new Composite("Composite X"); 85 | $comp2->add(new Leaf("Leaf XA")); 86 | $comp2->add(new Leaf("Leaf XB")); 87 | 88 | $comp->add($comp2); 89 | 90 | $root->add(new Leaf("Leaf C")); 91 | 92 | $leaf = new Leaf("Leaf D"); 93 | $root->add($leaf); 94 | $root->remove($leaf); 95 | 96 | $root->display(1); 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 | -------------------------------------------------------------------------------- /codes/CompositeCompany.php: -------------------------------------------------------------------------------- 1 | name = $name; 11 | } 12 | 13 | abstract public function add(Company $c); 14 | abstract public function remove(Company $c); 15 | abstract public function display($depth); 16 | abstract public function lineOfDuty();//职责,不同部门需要履行不同的职责 17 | } 18 | 19 | //具体公司类,实现接口 树枝节点 20 | class ConcreteCompany extends Company 21 | { 22 | private $childern = []; 23 | public function add(Company $c) 24 | { 25 | array_push($this->childern, $c); 26 | } 27 | 28 | public function remove(Company $c) 29 | { 30 | foreach ($this->childern as $key => $value) { 31 | if ($c === $value) { 32 | unset($this->childern[$key]); 33 | } 34 | } 35 | } 36 | 37 | // 显示其枝节点名称,并对其下级进行遍历 38 | public function display($depth) 39 | { 40 | echo str_repeat('-', $depth).$this->name."\n"; 41 | foreach ($this->childern as $component) { 42 | $component->display($depth + 2); 43 | } 44 | } 45 | 46 | public function lineOfDuty() 47 | { 48 | foreach ($this->childern as $company) { 49 | $company->lineOfDuty(); 50 | } 51 | } 52 | } 53 | 54 | 55 | //人力资源部 56 | class HRDepartment extends Company 57 | { 58 | public function add(Company $c){} 59 | 60 | public function remove(Company $c){} 61 | 62 | // 显示其枝节点名称,并对其下级进行遍历 63 | public function display($depth) 64 | { 65 | echo str_repeat('-', $depth).$this->name."\n"; 66 | } 67 | public function lineOfDuty() 68 | { 69 | echo $this->name."-----员工招聘培训\n"; 70 | } 71 | } 72 | 73 | //财务部 74 | class FinanceDepartment extends Company 75 | { 76 | public function add(Company $c){} 77 | 78 | public function remove(Company $c){} 79 | 80 | // 显示其枝节点名称,并对其下级进行遍历 81 | public function display($depth) 82 | { 83 | echo str_repeat('-', $depth).$this->name."\n"; 84 | } 85 | public function lineOfDuty() 86 | { 87 | echo $this->name."-----公司财务收支管理\n"; 88 | } 89 | } 90 | 91 | $root = new ConcreteCompany("北京总公司"); 92 | $root->add(new HRDepartment("北京人力资源部")); 93 | $root->add(new FinanceDepartment("北京财务部")); 94 | 95 | 96 | $comp = new ConcreteCompany("上海分公司"); 97 | $comp->add(new HRDepartment("上海人力资源部")); 98 | $comp->add(new FinanceDepartment("上海财务部")); 99 | $root->add($comp); 100 | 101 | $comp1 = new ConcreteCompany("南京分公司"); 102 | $comp1->add(new HRDepartment("南京人力资源部")); 103 | $comp1->add(new FinanceDepartment("南京财务部")); 104 | $comp->add($comp1); 105 | 106 | $comp2 = new ConcreteCompany("杭州分公司"); 107 | $comp2->add(new HRDepartment("杭州人力资源部")); 108 | $comp2->add(new FinanceDepartment("杭州财务部")); 109 | $comp->add($comp2); 110 | 111 | echo "结构图:\n"; 112 | $root->display(1); 113 | 114 | echo "\n职责:\n"; 115 | $root->lineOfDuty(); 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /codes/Decorator.php: -------------------------------------------------------------------------------- 1 | component = $component; 27 | } 28 | 29 | // 重写Operation(),实际执行的是component的Operation方法 30 | public function Operation() 31 | { 32 | if ($this->component != null) 33 | { 34 | $this->component->Operation(); 35 | } 36 | } 37 | } 38 | 39 | /** 40 | * ConcreteDecoratorA 41 | */ 42 | class ConcreteDecoratorA extends Decorator 43 | { 44 | // 本类的独有功能,以区别于ConcreteDecoratorB 45 | private $addedState; 46 | 47 | public function Operation() 48 | { 49 | // 首先运行原Component的Operation(),再执行本类的功能, 50 | // 如addedState,相当于对原Component进行了装饰 51 | parent::Operation(); 52 | $this->addedState = "ConcreteDecoratorA Status"; 53 | echo $this->addedState."\n"; 54 | echo "具体装饰对象A的操作.\n"; 55 | } 56 | } 57 | 58 | 59 | /** 60 | * ConcreteDecoratorB 61 | */ 62 | class ConcreteDecoratorB extends Decorator 63 | { 64 | public function Operation() 65 | { 66 | // 首先运行原Component的Operation(),再执行本类的功能, 67 | // 如addedBehavior,相当于对原Component进行了装饰 68 | parent::Operation(); 69 | $this->addedBehavior(); 70 | echo "具体装饰对象B的操作.\n"; 71 | } 72 | 73 | // 本类的独有功能,以区别于ConcreteDecoratorA 74 | private function addedBehavior() 75 | { 76 | echo "ConcreteDecoratorB Status.\n"; 77 | } 78 | } 79 | 80 | // 客户端代码 81 | // 装饰的方法是:首先用ConcreteComponent实例化对象c, 82 | // 然后用ConcreteDecoratorA的实例对象$di来包装$c, 83 | // 然后再用ConcreteDecoratorB的实例$d2包装$d1, 84 | // 最终执行$d2的Operation(); 85 | $c = new ConcreteComponent(); 86 | $d1 = new ConcreteDecoratorA(); 87 | $d2 = new ConcreteDecoratorB(); 88 | 89 | $d1->SetComponent($c); 90 | $d2->SetComponent($d1); 91 | $d2->Operation(); 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 | -------------------------------------------------------------------------------- /codes/Decorator2.php: -------------------------------------------------------------------------------- 1 | name = $name; 10 | } 11 | 12 | public function show() 13 | { 14 | echo "打扮".$this->name."\n"; 15 | } 16 | } 17 | 18 | 19 | // 服饰类 20 | class Finery 21 | { 22 | protected $person; 23 | 24 | public function decorate($person) 25 | { 26 | $this->person = $person; 27 | } 28 | 29 | public function show() 30 | { 31 | if ($this->person != null) 32 | { 33 | $this->person->show(); 34 | } 35 | } 36 | } 37 | 38 | // 具体服饰类 39 | class TShirts extends Finery 40 | { 41 | public function show() 42 | { 43 | echo "大T恤\n"; 44 | parent::show(); 45 | } 46 | } 47 | 48 | class BigTrouser extends Finery 49 | { 50 | public function show() 51 | { 52 | echo "跨裤\n"; 53 | parent::show(); 54 | } 55 | } 56 | 57 | class Sneakers extends Finery 58 | { 59 | public function show() 60 | { 61 | echo "破球鞋\n"; 62 | parent::show(); 63 | } 64 | } 65 | 66 | class Suit extends Finery 67 | { 68 | public function show() 69 | { 70 | echo "西装\n"; 71 | parent::show(); 72 | } 73 | } 74 | 75 | class Tie extends Finery 76 | { 77 | public function show() 78 | { 79 | echo "领带\n"; 80 | parent::show(); 81 | } 82 | } 83 | 84 | class LeatherShoes extends Finery 85 | { 86 | public function show() 87 | { 88 | echo "跨裤\n"; 89 | parent::show(); 90 | } 91 | } 92 | 93 | 94 | // 客户端代码 95 | $person = new Person("alex"); 96 | 97 | echo "\n第一种装扮:\n"; 98 | 99 | $sneakers = new Sneakers(); 100 | $bigTrouser = new BigTrouser(); 101 | $tShirts = new TShirts(); 102 | 103 | $sneakers->decorate($person); 104 | $bigTrouser->decorate($sneakers); 105 | $tShirts->decorate($bigTrouser); 106 | $tShirts->show(); 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /codes/Facade.php: -------------------------------------------------------------------------------- 1 | systemOne = new SubSystemOne(); 51 | $this->systemTwo = new SubSystemTwo(); 52 | $this->systemThree = new SubSystemThree(); 53 | $this->systemFour = new SubSystemFourth(); 54 | } 55 | 56 | public function methodA() 57 | { 58 | echo "方法A() ---\n"; 59 | $this->systemOne->methodOne(); 60 | $this->systemThree->methodThree(); 61 | } 62 | 63 | public function methodB() 64 | { 65 | echo "方法B() ---\n"; 66 | $this->systemTwo->methodTwo(); 67 | $this->systemFour->methodFourth(); 68 | } 69 | } 70 | 71 | //客户端代码 72 | 73 | $facade = new Facade(); 74 | $facade->methodA(); 75 | $facade->methodB(); 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /codes/FactoryMethod.php: -------------------------------------------------------------------------------- 1 | a = $a; 14 | } 15 | 16 | public function setB($b) 17 | { 18 | $this->b = $b; 19 | } 20 | 21 | public function getResult() 22 | { 23 | $result = 0; 24 | return $result; 25 | } 26 | } 27 | 28 | /** 29 | * add 30 | */ 31 | class OperationAdd extends Operation 32 | { 33 | public function getResult() 34 | { 35 | return $this->a + $this->b; 36 | } 37 | } 38 | 39 | /** 40 | * Mul 41 | */ 42 | class OperationMul extends Operation 43 | { 44 | public function getResult() 45 | { 46 | return $this->a * $this->b; 47 | } 48 | } 49 | 50 | /** 51 | * sub 52 | */ 53 | class OperationSub extends Operation 54 | { 55 | public function getResult() 56 | { 57 | return $this->a - $this->b; 58 | } 59 | } 60 | 61 | /** 62 | * div 63 | */ 64 | class OperationDiv extends Operation 65 | { 66 | public function getResult() 67 | { 68 | $this->a / $this->b; 69 | } 70 | } 71 | 72 | ////////////////////////////////////// 73 | 74 | interface IFactory 75 | { 76 | public function CreateOperation(); 77 | } 78 | 79 | class AddFactory implements IFactory 80 | { 81 | public function CreateOperation() 82 | { 83 | return new OperationAdd(); 84 | } 85 | } 86 | 87 | class SubFactory implements IFactory 88 | { 89 | public function CreateOperation() 90 | { 91 | return new OperationSub(); 92 | } 93 | } 94 | 95 | class MulFactory implements IFactory 96 | { 97 | public function CreateOperation() 98 | { 99 | return new OperationMul(); 100 | } 101 | } 102 | 103 | class DivFactory implements IFactory 104 | { 105 | public function CreateOperation() 106 | { 107 | return new OperationDiv(); 108 | } 109 | } 110 | 111 | //客户端代码 112 | $operationFactory = new AddFactory(); 113 | $operation = $operationFactory->CreateOperation(); 114 | $operation->setA(10); 115 | $operation->setB(10); 116 | echo $operation->getResult()."\n"; -------------------------------------------------------------------------------- /codes/Interpreter.php: -------------------------------------------------------------------------------- 1 | input = $input; 30 | } 31 | 32 | public function getInput() 33 | { 34 | return $this->input; 35 | } 36 | 37 | private $output; 38 | public function setOutput($output) 39 | { 40 | $this->output = $output; 41 | } 42 | 43 | public function getOutput() 44 | { 45 | return $this->output; 46 | } 47 | } 48 | 49 | 50 | $context = new Context(); 51 | $syntax = []; 52 | array_push($syntax, new TerminalExpression()); 53 | array_push($syntax, new NonTerminalExpression()); 54 | array_push($syntax, new TerminalExpression()); 55 | array_push($syntax, new TerminalExpression()); 56 | 57 | foreach ($syntax as $value) { 58 | $value->interpret($context); 59 | } 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /codes/Iterator.php: -------------------------------------------------------------------------------- 1 | aggregate = $aggregate; 25 | } 26 | 27 | public function first() 28 | { 29 | return $this->aggregate[0]; 30 | } 31 | 32 | public function next() 33 | { 34 | $ret = null; 35 | $this->current++; 36 | if ($this->current < count($this->aggregate)) 37 | { 38 | $ret = $this->aggregate[$this->current]; 39 | } 40 | return $ret; 41 | } 42 | 43 | public function isDone() 44 | { 45 | return $this->current >= count($this->aggregate); 46 | } 47 | 48 | public function currentItem() 49 | { 50 | return $this->aggregate[$this->current]; 51 | } 52 | } 53 | 54 | class ConcreteAggregate extends Aggregate 55 | { 56 | private $items = []; 57 | 58 | public function createIterator() 59 | { 60 | return new ConcreteIterator($this); 61 | } 62 | 63 | public function count() 64 | { 65 | return count($this->items); 66 | } 67 | 68 | public function add($item) 69 | { 70 | array_push($this->items, $item); 71 | } 72 | 73 | public function items() 74 | { 75 | return $this->items; 76 | } 77 | } 78 | 79 | //客户端代码 80 | $a = new ConcreteAggregate(); 81 | $a->add("大鸟"); 82 | $a->add("小菜"); 83 | $a->add("行李"); 84 | $a->add("老外"); 85 | $a->add("公交内部员工"); 86 | $a->add("小偷"); 87 | 88 | $i = new ConcreteIterator($a->items()); 89 | 90 | while (!$i->isDone()) 91 | { 92 | echo $i->currentItem()." 请买票\n"; 93 | $i->next(); 94 | } 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /codes/Mediator.php: -------------------------------------------------------------------------------- 1 | mediator = $mediator; 15 | } 16 | } 17 | 18 | class ConcreteMediator extends Mediator 19 | { 20 | private $colleague1; 21 | private $colleague2; 22 | 23 | public function setColleague1(Colleague $colleague) 24 | { 25 | $this->colleague1 = $colleague; 26 | } 27 | 28 | public function setColleague2(Colleague $colleague) 29 | { 30 | $this->colleague2 = $colleague; 31 | } 32 | 33 | public function send($message, Colleague $colleague) 34 | { 35 | if($this->colleague1 == $colleague) 36 | { 37 | $this->colleague2->notify($message); 38 | } else { 39 | $this->colleague1->notify($message); 40 | } 41 | } 42 | } 43 | 44 | class ConcreteColleague1 extends Colleague 45 | { 46 | public function send($message) 47 | { 48 | $this->mediator->send($message, $this); 49 | } 50 | 51 | public function notify($message) 52 | { 53 | echo "ConcreteColleague1 ".$message."\n"; 54 | } 55 | } 56 | 57 | class ConcreteColleague2 extends Colleague 58 | { 59 | public function send($message) 60 | { 61 | $this->mediator->send($message, $this); 62 | } 63 | 64 | public function notify($message) 65 | { 66 | echo "ConcreteColleague2 ".$message."\n";; 67 | } 68 | } 69 | 70 | //client 71 | 72 | $mediator = new ConcreteMediator(); 73 | $c1 = new ConcreteColleague1($mediator); 74 | $c2 = new ConcreteColleague2($mediator); 75 | 76 | $mediator->setColleague1($c1); 77 | $mediator->setColleague2($c2); 78 | 79 | $c1->send('do you eat?'); 80 | $c2->send('no, do you want to invite me to dinner?'); -------------------------------------------------------------------------------- /codes/Memento.php: -------------------------------------------------------------------------------- 1 | state = $state; 11 | } 12 | public function getState() 13 | { 14 | return $this->state; 15 | } 16 | 17 | //创建备忘录,将当前需要保存的信息导入并实例化出一个memento对象。 18 | public function createMemento() 19 | { 20 | return new Memento($this->state); 21 | } 22 | 23 | //恢复备忘录,将memento导入并将相关数据恢复。 24 | public function setMemento(Memento $memento) 25 | { 26 | $this->state = $memento->getState(); 27 | } 28 | 29 | //显示数据 30 | public function show() 31 | { 32 | echo "status ".$this->state."\n"; 33 | } 34 | } 35 | 36 | //备忘录类 37 | 38 | class Memento 39 | { 40 | private $state; 41 | 42 | //构造方法,将相关数据导入 43 | function __construct($state) 44 | { 45 | $this->state = $state; 46 | } 47 | 48 | //获取需要保存的数据,可以多个 49 | public function getState() 50 | { 51 | return $this->state; 52 | } 53 | } 54 | 55 | //管理者类 56 | class CareTaker 57 | { 58 | private $memento; 59 | 60 | public function getMemento() 61 | { 62 | return $this->memento; 63 | } 64 | 65 | //设置备忘录 66 | public function setMemento(Memento $memento) 67 | { 68 | $this->memento = $memento; 69 | } 70 | } 71 | 72 | //客户端程序 73 | $o = new Originator(); //Originator初始状态,状态属性on 74 | $o->setState("On"); 75 | $o->show(); 76 | 77 | //保存状态时,由于有了很好的封装,可以隐藏Originator的实现细节 78 | $c = new CareTaker(); 79 | $c->setMemento($o->createMemento()); 80 | 81 | // 改变属性 82 | $o->setState("Off"); 83 | $o->show(); 84 | 85 | // 恢复属性 86 | $o->setMemento($c->getMemento()); 87 | $o->show(); 88 | -------------------------------------------------------------------------------- /codes/Observer.php: -------------------------------------------------------------------------------- 1 | observers, $observer); 10 | } 11 | 12 | public function detatch($observer) 13 | { 14 | foreach ($this->observers as $key => $value) { 15 | if ($observer === $value) { 16 | unset($this->observers[$key]); 17 | } 18 | } 19 | } 20 | 21 | public function notify() 22 | { 23 | foreach ($this->observers as $observer) { 24 | $observer->update(); 25 | } 26 | } 27 | } 28 | 29 | abstract class Observer 30 | { 31 | abstract function update(); 32 | } 33 | 34 | class ConcreteSubject extends Subject 35 | { 36 | private $subjectState; 37 | public function setState($state) 38 | { 39 | $this->subjectState = $state; 40 | } 41 | 42 | public function getState() 43 | { 44 | return $this->subjectState; 45 | } 46 | } 47 | 48 | class ConcreteObserver extends Observer 49 | { 50 | private $name; 51 | private $subject; 52 | 53 | function __construct(ConcreteSubject $subject, $name) 54 | { 55 | $this->subject = $subject; 56 | $this->name = $name; 57 | } 58 | 59 | public function update() 60 | { 61 | echo "观察者 ".$this->name."的新状态是:".$this->subject->getState()."\n"; 62 | } 63 | } 64 | 65 | $s = new ConcreteSubject(); 66 | $s->attach(new ConcreteObserver($s, "x")); 67 | $s->attach(new ConcreteObserver($s, "y")); 68 | $z = new ConcreteObserver($s, "z"); 69 | $s->attach($z); 70 | $s->detatch($z); 71 | $s->setState('ABC'); 72 | $s->notify(); 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /codes/Operation.php: -------------------------------------------------------------------------------- 1 | a = $a; 11 | } 12 | 13 | public function setB($b) 14 | { 15 | $this->b = $b; 16 | } 17 | 18 | public function getResult() 19 | { 20 | $result = 0; 21 | return $result; 22 | } 23 | } 24 | 25 | /** 26 | * add 27 | */ 28 | class OperationAdd extends Operation 29 | { 30 | public function getResult() 31 | { 32 | return $this->a + $this->b; 33 | } 34 | } 35 | 36 | /** 37 | * Mul 38 | */ 39 | class OperationMul extends Operation 40 | { 41 | public function getResult() 42 | { 43 | return $this->a * $this->b; 44 | } 45 | } 46 | 47 | /** 48 | * sub 49 | */ 50 | class OperationSub extends Operation 51 | { 52 | public function getResult() 53 | { 54 | return $this->a - $this->b; 55 | } 56 | } 57 | 58 | /** 59 | * div 60 | */ 61 | class OperationDiv extends Operation 62 | { 63 | public function getResult() 64 | { 65 | $this->a / $this->b; 66 | } 67 | } 68 | 69 | 70 | /** 71 | * operation factory 72 | */ 73 | class OperationFactory 74 | { 75 | public static function createOperation($operation) 76 | { 77 | switch ($operation) { 78 | case '+': 79 | $oper = new OperationAdd(); 80 | break; 81 | case '-': 82 | $oper = new OperationSub(); 83 | break; 84 | case '/': 85 | $oper = new OperationDiv(); 86 | break; 87 | case '*': 88 | $oper = new OperationMul(); 89 | break; 90 | } 91 | return $oper; 92 | } 93 | } 94 | 95 | $operation = OperationFactory::createOperation('+'); 96 | $operation->setA(1); 97 | $operation->setB(2); 98 | echo $operation->getResult()."\n"; 99 | -------------------------------------------------------------------------------- /codes/Proxy.php: -------------------------------------------------------------------------------- 1 | name = $name; 10 | } 11 | 12 | public function getName() 13 | { 14 | return $this->name; 15 | } 16 | } 17 | 18 | // 代理接口 19 | interface GiveGift 20 | { 21 | public function GiveDolls(); 22 | public function GiveFlowers(); 23 | public function GiveChocolate(); 24 | } 25 | 26 | // 代理实现送礼物接口 27 | class Proxy implements GiveGift 28 | { 29 | protected $pursuit; 30 | 31 | function __construct(SchoolGirl $girl) 32 | { 33 | $this->pursuit = new Pursuit($girl); 34 | } 35 | 36 | public function GiveDolls() 37 | { 38 | $this->pursuit->GiveDolls(); 39 | } 40 | 41 | public function GiveFlowers() 42 | { 43 | $this->pursuit->GiveFlowers(); 44 | } 45 | 46 | public function GiveChocolate() 47 | { 48 | $this->pursuit->GiveChocolate(); 49 | } 50 | } 51 | 52 | // 追求者类实现送礼物接口 53 | class Pursuit implements GiveGift 54 | { 55 | protected $girl; 56 | function __construct(SchoolGirl $girl) 57 | { 58 | $this->girl = $girl; 59 | } 60 | 61 | public function GiveDolls() 62 | { 63 | echo $this->girl->getName()." 送你娃娃\n"; 64 | } 65 | 66 | public function GiveFlowers() 67 | { 68 | echo $this->girl->getName()." 送你花\n"; 69 | } 70 | 71 | public function GiveChocolate() 72 | { 73 | echo $this->girl->getName()." 送你巧克力\n"; 74 | } 75 | } 76 | 77 | // 客户端代码 78 | $girl = new SchoolGirl('李梅'); 79 | $proxy = new Proxy($girl); 80 | $proxy->GiveDolls(); 81 | $proxy->GiveChocolate(); 82 | $proxy->GiveFlowers(); 83 | -------------------------------------------------------------------------------- /codes/Singleton.php: -------------------------------------------------------------------------------- 1 | strategy = $strategy; 56 | } 57 | 58 | public function contextInterface() 59 | { 60 | $this->strategy->AlgorithmInterface(); 61 | } 62 | } 63 | 64 | //客户端代码 65 | $context = new Context(new ConcreteStrategyA()); 66 | $context->contextInterface(); 67 | 68 | $context = new Context(new ConcreteStrategyB()); 69 | $context->contextInterface(); 70 | 71 | $context = new Context(new ConcreteStrategyC()); 72 | $context->contextInterface(); 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /codes/Template.php: -------------------------------------------------------------------------------- 1 | answer1()."\n"; 10 | } 11 | 12 | public function TestQuestion2() 13 | { 14 | echo "杨过、程英、陆无双铲除了情花,造成[]a.使这种植物不在害人 b.使一种珍惜物种灭绝 c.破坏了那个生态圈的生态平衡 d.造成该地区沙漠化 \n"; 15 | echo "答案 ".$this->answer2()."\n"; 16 | } 17 | 18 | public function TestQuestion3() 19 | { 20 | echo "蓝凤凰致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[]a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对 \n"; 21 | echo "答案 ".$this->answer3()."\n"; 22 | } 23 | 24 | protected function answer1() 25 | { 26 | return ''; 27 | } 28 | 29 | protected function answer2() 30 | { 31 | return ''; 32 | } 33 | 34 | protected function answer3() 35 | { 36 | return ''; 37 | } 38 | } 39 | 40 | // 学生甲抄的试卷 41 | class TestPaperA extends TestPaper 42 | { 43 | protected function answer1() 44 | { 45 | return 'a'; 46 | } 47 | 48 | protected function answer2() 49 | { 50 | return 'b'; 51 | } 52 | 53 | protected function answer3() 54 | { 55 | return 'c'; 56 | } 57 | } 58 | 59 | // 学生乙抄的试卷 60 | // 学生甲抄的试卷 61 | class TestPaperB extends TestPaper 62 | { 63 | protected function answer1() 64 | { 65 | return 'd'; 66 | } 67 | 68 | protected function answer2() 69 | { 70 | return 'c'; 71 | } 72 | 73 | protected function answer3() 74 | { 75 | return 'a'; 76 | } 77 | } 78 | 79 | 80 | // 客户端代码 81 | 82 | echo "学生甲抄的试卷: \n"; 83 | $student = new TestPaperA(); 84 | $student->TestQuestion1(); 85 | $student->TestQuestion2(); 86 | $student->TestQuestion3(); 87 | echo "学生乙抄的试卷: \n"; 88 | $student2 = new TestPaperB(); 89 | $student2->TestQuestion1(); 90 | $student2->TestQuestion2(); 91 | $student2->TestQuestion3(); 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /codes/Visitor.php: -------------------------------------------------------------------------------- 1 | getManConclusion($this); 59 | } 60 | } 61 | 62 | class Woman extends Person 63 | { 64 | public function accept(Action $visitor) 65 | { 66 | $visitor->getWomanConclusion($this); 67 | } 68 | } 69 | 70 | class ObjectStructure 71 | { 72 | private $person = []; 73 | 74 | public function acctch(Person $person) 75 | { 76 | array_push($this->person, $person); 77 | } 78 | 79 | public function display(Action $visitor) 80 | { 81 | foreach ($this->person as $person) { 82 | $person->accept($visitor); 83 | } 84 | } 85 | } 86 | 87 | 88 | $o = new ObjectStructure(); 89 | $o->acctch(new Man()); 90 | $o->acctch(new Woman()); 91 | 92 | // 成功时的反应 93 | $v1 = new Success(); 94 | $o->display($v1); 95 | 96 | 97 | $v2 = new Failing(); 98 | $o->display($v2); 99 | 100 | 101 | $v3 = new Amativeness(); 102 | $o->display($v3); 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 | -------------------------------------------------------------------------------- /files/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/files/.DS_Store -------------------------------------------------------------------------------- /files/chapter1.md: -------------------------------------------------------------------------------- 1 | ### 第一章 代码无错就是优 ---简单工厂模式 2 | 3 | 1.简单工厂模式 4 | ```php 5 | a = $a; 18 | } 19 | 20 | public function setB($b) 21 | { 22 | $this->b = $b; 23 | } 24 | 25 | public function getResult() 26 | { 27 | $result = 0; 28 | return $result; 29 | } 30 | } 31 | 32 | /** 33 | * Add 34 | */ 35 | class OperationAdd extends Operation 36 | { 37 | public function getResult() 38 | { 39 | return $this->a + $this->b; 40 | } 41 | } 42 | 43 | /** 44 | * Mul 45 | */ 46 | class OperationMul extends Operation 47 | { 48 | public function getResult() 49 | { 50 | return $this->a * $this->b; 51 | } 52 | } 53 | 54 | /** 55 | * Sub 56 | */ 57 | class OperationSub extends Operation 58 | { 59 | public function getResult() 60 | { 61 | return $this->a - $this->b; 62 | } 63 | } 64 | 65 | /** 66 | * Div 67 | */ 68 | class OperationDiv extends Operation 69 | { 70 | public function getResult() 71 | { 72 | return $this->a / $this->b; 73 | } 74 | } 75 | 76 | /** 77 | * Operation Factory 78 | */ 79 | class OperationFactory 80 | { 81 | public static function createOperation($operation) 82 | { 83 | switch ($operation) { 84 | case '+': 85 | $oper = new OperationAdd(); 86 | break; 87 | case '-': 88 | $oper = new OperationSub(); 89 | break; 90 | case '/': 91 | $oper = new OperationDiv(); 92 | break; 93 | case '*': 94 | $oper = new OperationMul(); 95 | break; 96 | } 97 | 98 | return $oper; 99 | } 100 | } 101 | 102 | // 客户端代码 103 | $operation = OperationFactory::createOperation('+'); 104 | $operation->setA(1); 105 | $operation->setB(2); 106 | echo $operation->getResult() . PHP_EOL; 107 | ``` 108 | 109 | 110 | 111 | 总结 112 | 113 | > 学会通过分封装,继承,多态把程序的藕合度降低 114 | 115 | > 复用,不是复制! 116 | 117 | > 高内聚,低耦合 118 | 119 | 下一章:[第二章 商场促销 --- 策略模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter2.md) 120 | -------------------------------------------------------------------------------- /files/chapter10.md: -------------------------------------------------------------------------------- 1 | ### 第十章 考题抄错会做也白搭 --- 模版方法模式 2 | ```php 3 | answer1()."\n"; 12 | } 13 | 14 | public function TestQuestion2() 15 | { 16 | echo "杨过、程英、陆无双铲除了情花,造成[]a.使这种植物不在害人 b.使一种珍惜物种灭绝 c.破坏了那个生态圈的生态平衡 d.造成该地区沙漠化 \n"; 17 | echo "答案 ".$this->answer2()."\n"; 18 | } 19 | 20 | public function TestQuestion3() 21 | { 22 | echo "蓝凤凰致使华山师徒、桃谷六仙呕吐不止,如果你是大夫,会给他们开什么药[]a.阿司匹林 b.牛黄解毒片 c.氟哌酸 d.让他们喝大量的生牛奶 e.以上全不对 \n"; 23 | echo "答案 ".$this->answer3()."\n"; 24 | } 25 | 26 | protected function answer1() 27 | { 28 | return ''; 29 | } 30 | 31 | protected function answer2() 32 | { 33 | return ''; 34 | } 35 | 36 | protected function answer3() 37 | { 38 | return ''; 39 | } 40 | } 41 | 42 | // 学生甲抄的试卷 43 | class TestPaperA extends TestPaper 44 | { 45 | protected function answer1() 46 | { 47 | return 'a'; 48 | } 49 | 50 | protected function answer2() 51 | { 52 | return 'b'; 53 | } 54 | 55 | protected function answer3() 56 | { 57 | return 'c'; 58 | } 59 | } 60 | 61 | // 学生乙抄的试卷 62 | // 学生甲抄的试卷 63 | class TestPaperB extends TestPaper 64 | { 65 | protected function answer1() 66 | { 67 | return 'd'; 68 | } 69 | 70 | protected function answer2() 71 | { 72 | return 'c'; 73 | } 74 | 75 | protected function answer3() 76 | { 77 | return 'a'; 78 | } 79 | } 80 | 81 | 82 | // 客户端代码 83 | 84 | echo "学生甲抄的试卷: \n"; 85 | $student = new TestPaperA(); 86 | $student->TestQuestion1(); 87 | $student->TestQuestion2(); 88 | $student->TestQuestion3(); 89 | echo "学生乙抄的试卷: \n"; 90 | $student2 = new TestPaperB(); 91 | $student2->TestQuestion1(); 92 | $student2->TestQuestion2(); 93 | $student2->TestQuestion3(); 94 | ``` 95 | 96 | 总结: 97 | 98 | > ***模版方法模式***,定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模版方法使得子类可以不改变算法的节结构即可重定义该算法的某些特定步骤。 99 | 100 | > 既然用了继承,并且肯定这个继承有意义,就应该要成为子类的模版,所有重复的代码都应该要上升到父类去,而不是让每个子类去重复。 101 | 102 | > 当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其中个别步骤在更详细的层次上的实现可能不同时,我们通常考虑用模版方法模式来处理。 103 | 104 | > 模版方法模式是通过把不变行为搬移到超类,去除子类中的重复代码来体现它的优势。提供了一个很好的代码复用平台。 105 | 106 | > 当不变的和可变的行为在方法的子类实现中混合在一起的时候,不变的行为就会在子类中重复出现。通过模版方法把这些行为搬移到单一的地方,这样就帮助子类摆脱重复的不变行为的纠缠。 107 | 108 | 上一章:[第九章 简历复印 --- 原型模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter9.md) 109 | 110 | 下一章:[第十一章 无熟人难办事 --- 迪米特法则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter11.md) -------------------------------------------------------------------------------- /files/chapter11.md: -------------------------------------------------------------------------------- 1 | ### 第十一章 无熟人难办事 --- 迪米特法则 2 | 3 | 总结: 4 | 5 | > ***迪米特法则***,如果两个类不彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。 6 | 7 | > 在类的结构设计上,每一个类都应当 尽量降低成员的访问权限 8 | 9 | > 类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及。 10 | 11 | 12 | 上一章:[第十章 考题抄错会做也白搭 --- 模版方法模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter10.md) 13 | 14 | 下一章:[第十二章 牛市股票还会亏钱 --- 外观模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter12.md) -------------------------------------------------------------------------------- /files/chapter12.md: -------------------------------------------------------------------------------- 1 | ### 第十二章 牛市股票还会亏钱 --- 外观模式 2 | 3 | ```php 4 | systemOne = new SubSystemOne(); 54 | $this->systemTwo = new SubSystemTwo(); 55 | $this->systemThree = new SubSystemThree(); 56 | $this->systemFour = new SubSystemFourth(); 57 | } 58 | 59 | public function methodA() 60 | { 61 | echo "方法A() ---\n"; 62 | $this->systemOne->methodOne(); 63 | $this->systemThree->methodThree(); 64 | } 65 | 66 | public function methodB() 67 | { 68 | echo "方法B() ---\n"; 69 | $this->systemTwo->methodTwo(); 70 | $this->systemFour->methodFourth(); 71 | } 72 | } 73 | 74 | //客户端代码 75 | 76 | $facade = new Facade(); 77 | $facade->methodA(); 78 | $facade->methodB(); 79 | 80 | ``` 81 | 82 | 总结: 83 | 84 | > ***外观模式***,为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更容易使用。 85 | 86 | > 首先,在设计初期阶段,应该要有意识的将不同的两个层分离,层与层之间建立外观Facade;其次,在开发阶段,子系统往往因为不断的重构演化而变得越来越复杂,增加外观Facade可以提供一个简单的接口,减少它们之间的依赖;另外在维护一个遗留的大型系统时,可能这个系统已经非常难以维护和扩展了,为新系统开发一个外观Facade类,来提供设计粗糙或高度复杂的遗留代码的比较清晰简单的接口,让系统与Facade对象交互,Facade与遗留代码交互所有复杂的工作 87 | 88 | 上一章:[第十一章 无熟人难办事 --- 迪米特法则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter11.md) 89 | 90 | 下一章:[第十三章 好菜每回味不同 --- 建造者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter13.md) -------------------------------------------------------------------------------- /files/chapter13.md: -------------------------------------------------------------------------------- 1 | ### 第十三章 好菜每回味不同 --- 建造者模式 2 | 3 | ```php 4 | personBuilder = $personBuilder; 90 | } 91 | 92 | public function CreatePerson() 93 | { 94 | $this->personBuilder->BuildHead(); 95 | $this->personBuilder->BuildBody(); 96 | $this->personBuilder->BuildArmRight(); 97 | $this->personBuilder->BuildArmLeft(); 98 | $this->personBuilder->BuildLegLeft(); 99 | $this->personBuilder->BuildLegRight(); 100 | } 101 | } 102 | 103 | 104 | //客户端代码 105 | 106 | echo "苗条的:\n"; 107 | $thinDirector = new PersonDirector(new PersonThinBuilder()); 108 | $thinDirector->CreatePerson(); 109 | 110 | echo "\n胖的:\n"; 111 | $fatDirector = new PersonDirector(new PersonFatBuilder()); 112 | $fatDirector->CreatePerson(); 113 | ``` 114 | 115 | 总结: 116 | 117 | > ***建造者模式***,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。 118 | 119 | > 如果我们用了建造者模式,那么用户只需要指定需要建造的类型就可以得到他们,而具体建造的过程和细节就不需要知道了。 120 | 121 | > 主要用于创建一些复杂的对象,这些对象内部构建间的建造顺序通常是稳定的,但对象内部的构建通畅面临着复杂的变化。 122 | 123 | > 建造者模式是在当创建复杂对象的算法应该独立于改对象的组成部分以及它们的装配方式时适用的模式。 124 | 125 | 上一章:[第十二章 牛市股票还会亏钱 --- 外观模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter12.md) 126 | 127 | 下一章:[第十四章 老板回来,我不知道 --- 观察者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter14.md) -------------------------------------------------------------------------------- /files/chapter14.md: -------------------------------------------------------------------------------- 1 | ### 第十四章 老板回来,我不知道 --- 观察者模式 2 | 3 | ```php 4 | observers, $observer); 13 | } 14 | 15 | public function detatch($observer) 16 | { 17 | foreach ($this->observers as $key => $value) { 18 | if ($observer === $value) { 19 | unset($this->observers[$key]); 20 | } 21 | } 22 | } 23 | 24 | public function notify() 25 | { 26 | foreach ($this->observers as $observer) { 27 | $observer->update(); 28 | } 29 | } 30 | } 31 | 32 | abstract class Observer 33 | { 34 | abstract function update(); 35 | } 36 | 37 | class ConcreteSubject extends Subject 38 | { 39 | private $subjectState; 40 | public function setState($state) 41 | { 42 | $this->subjectState = $state; 43 | } 44 | 45 | public function getState() 46 | { 47 | return $this->subjectState; 48 | } 49 | } 50 | 51 | class ConcreteObserver extends Observer 52 | { 53 | private $name; 54 | private $subject; 55 | 56 | function __construct(ConcreteSubject $subject, $name) 57 | { 58 | $this->subject = $subject; 59 | $this->name = $name; 60 | } 61 | 62 | public function update() 63 | { 64 | echo "观察者 ".$this->name."的新状态是:".$this->subject->getState()."\n"; 65 | } 66 | } 67 | 68 | $s = new ConcreteSubject(); 69 | $s->attach(new ConcreteObserver($s, "x")); 70 | $s->attach(new ConcreteObserver($s, "y")); 71 | $z = new ConcreteObserver($s, "z"); 72 | $s->attach($z); 73 | $s->detatch($z); 74 | $s->setState('ABC'); 75 | $s->notify(); 76 | ``` 77 | 78 | 总结: 79 | > ***观察者模式***,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。 80 | 81 | > 将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。 82 | 83 | > 观察者模式所做的工作其实就是在接触耦合。让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。 84 | 85 | 上一章:[第十三章 好菜每回味不同 --- 建造者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter13.md) 86 | 87 | 下一章:[第十五章 就不能不换DB吗? --- 抽象工厂模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter15.md) -------------------------------------------------------------------------------- /files/chapter16.md: -------------------------------------------------------------------------------- 1 | ### 第十六章 无尽加班何时休 --- 状态模式 2 | 3 | ```php 4 | //工作状态 5 | abstract class State 6 | { 7 | abstract public function WriteProgram(Work $w); 8 | } 9 | 10 | class ForenoonState extends State 11 | { 12 | public function WriteProgram(Work $w) 13 | { 14 | if ($w->getHour() < 12) { 15 | echo "当前时间:".$w->getHour()." 上午工作,精神百倍\n"; 16 | } else { 17 | $w->setState(new NoonState()); 18 | $w->WriteProgram(); 19 | } 20 | } 21 | } 22 | 23 | class NoonState extends State 24 | { 25 | public function WriteProgram(Work $w) 26 | { 27 | if ($w->getHour() < 13) { 28 | echo "当前时间:".$w->getHour()." 饿了,午饭;犯困,午休\n"; 29 | } else { 30 | $w->setState(new AfterNoonState()); 31 | $w->WriteProgram(); 32 | } 33 | } 34 | } 35 | 36 | class AfterNoonState extends State 37 | { 38 | public function WriteProgram(Work $w) 39 | { 40 | if ($w->getHour() < 17) { 41 | echo "当前时间:".$w->getHour()." 下午状态不错,继续努力\n"; 42 | } else { 43 | $w->setState(new EveningState()); 44 | $w->WriteProgram(); 45 | } 46 | } 47 | } 48 | 49 | class EveningState extends State 50 | { 51 | public function WriteProgram(Work $w) 52 | { 53 | if ($w->getTaskFinishedState()) { 54 | //如果完成任务,下班 55 | $w->setState(new RestState()); 56 | $w->WriteProgram(); 57 | } else { 58 | if ($w->getHour() < 21) { 59 | echo "当前时间:".$w->getHour()." 加班哦,疲惫之极\n"; 60 | } else { 61 | //超过21点,则转入睡眠工作状态 62 | $w->setState(new SleepingState()); 63 | $w->WriteProgram(); 64 | } 65 | } 66 | } 67 | } 68 | 69 | class SleepingState extends State 70 | { 71 | public function WriteProgram(Work $w) 72 | { 73 | echo "当前时间:".$w->getHour()." 不行了,睡觉\n"; 74 | } 75 | } 76 | 77 | class RestState extends State 78 | { 79 | public function WriteProgram(Work $w) 80 | { 81 | echo "当前时间:".$w->getHour()." 下班回家\n"; 82 | } 83 | } 84 | 85 | class Work 86 | { 87 | private $current; 88 | 89 | function __construct() 90 | { 91 | $this->current = new ForenoonState(); 92 | } 93 | 94 | private $hour; 95 | public function getHour() 96 | { 97 | return $this->hour; 98 | } 99 | public function setHour($hour) 100 | { 101 | $this->hour = $hour; 102 | } 103 | 104 | private $finished = false; 105 | public function setTaskFinished($bool) 106 | { 107 | $this->finished = $bool; 108 | } 109 | public function getTaskFinishedState() 110 | { 111 | return $this->finished; 112 | } 113 | 114 | public function setState(State $state) 115 | { 116 | $this->current = $state; 117 | } 118 | 119 | public function WriteProgram() 120 | { 121 | $this->current->WriteProgram($this); 122 | } 123 | } 124 | 125 | //客户端代码 126 | $emergencyProjects = new Work(); 127 | $emergencyProjects->setHour(9); 128 | $emergencyProjects->WriteProgram(); 129 | $emergencyProjects->setHour(10); 130 | $emergencyProjects->WriteProgram(); 131 | $emergencyProjects->setHour(12); 132 | $emergencyProjects->WriteProgram(); 133 | $emergencyProjects->setHour(13); 134 | $emergencyProjects->WriteProgram(); 135 | $emergencyProjects->setHour(14); 136 | $emergencyProjects->WriteProgram(); 137 | $emergencyProjects->setHour(17); 138 | 139 | $emergencyProjects->setTaskFinished(false); 140 | $emergencyProjects->WriteProgram(); 141 | 142 | $emergencyProjects->setHour(19); 143 | $emergencyProjects->WriteProgram(); 144 | $emergencyProjects->setHour(22); 145 | $emergencyProjects->WriteProgram(); 146 | 147 | ``` 148 | 149 | 总结: 150 | 151 | > ***状态模式***,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。 152 | 153 | > 面向对象设计其实就是希望做到代码的责任分解。 154 | 155 | > 状态模式主要解决的当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简单化。 156 | 157 | > 将于特定状态相关的行为局部化,并且将不同状态的行为分割开来。 158 | 159 | > 将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义的子类可以很容易地增加新的状态和转换。 160 | 161 | > 消除了庞大的条件分支语句。 162 | 163 | > 状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少项目之间的依赖。 164 | 165 | > 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。 166 | 167 | 168 | 上一章:[第十五章 就不能不换DB吗? --- 抽象工厂模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter15.md) 169 | 170 | 下一章:[第十七章 在NBA我需要翻译 --- 适配器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter17.md) -------------------------------------------------------------------------------- /files/chapter17.md: -------------------------------------------------------------------------------- 1 | ### 第十七章 在NBA我需要翻译 --- 适配器模式 2 | 3 | ```php 4 | name = $name; 14 | } 15 | 16 | abstract public function Attack(); 17 | abstract public function Defense(); 18 | } 19 | 20 | //前锋 21 | class Forwards extends Player 22 | { 23 | public function Attack() 24 | { 25 | echo "前锋:".$this->name." 进攻\n"; 26 | } 27 | public function Defense() 28 | { 29 | echo "前锋:".$this->name." 防守\n"; 30 | } 31 | } 32 | 33 | //中锋 34 | class Center extends Player 35 | { 36 | function __construct() 37 | { 38 | parent::__construct(); 39 | } 40 | 41 | public function Attack() 42 | { 43 | echo "中锋:".$this->name." 进攻\n"; 44 | } 45 | public function Defense() 46 | { 47 | echo "中锋:".$this->name." 防守\n"; 48 | } 49 | } 50 | 51 | //外籍中锋 52 | class ForeignCenter 53 | { 54 | private $name; 55 | public function setName($name) 56 | { 57 | $this->name = $name; 58 | } 59 | 60 | public function getName() 61 | { 62 | return $this->name; 63 | } 64 | 65 | public function 进攻() 66 | { 67 | echo "外籍中锋:".$this->name." 进攻\n"; 68 | } 69 | 70 | public function 防守() 71 | { 72 | echo "外籍中锋:".$this->name." 防守\n"; 73 | } 74 | } 75 | 76 | //翻译者 77 | class Translator extends Player 78 | { 79 | private $foreignCenter; 80 | 81 | function __construct($name) 82 | { 83 | $this->foreignCenter = new ForeignCenter(); 84 | $this->foreignCenter->setName($name); 85 | } 86 | 87 | public function Attack() 88 | { 89 | $this->foreignCenter->进攻(); 90 | } 91 | public function Defense() 92 | { 93 | $this->foreignCenter->防守(); 94 | } 95 | 96 | } 97 | 98 | // 客户端代码 99 | $forwards = new Forwards("巴蒂尔"); 100 | $forwards->Attack(); 101 | $forwards->Defense(); 102 | 103 | $translator = new Translator("姚明"); 104 | $translator->Attack(); 105 | $translator->Defense(); 106 | ``` 107 | 108 | 总结: 109 | 110 | > ***适配器模式***,将一个类的接口转化成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 111 | 112 | > 系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类。但是接口又与复用环境要求不一致的情况。 113 | 114 | > 两个类所做的事情相同或相似,但是具有不同的接口时要使用它。 115 | 116 | > 在双方都不太容易修改的时候再使用适配器模式适配。 117 | 118 | 上一章:[第十六章 无尽加班何时休 --- 状态模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter16.md) 119 | 120 | 下一章:[第十八章 如果再回到从前 --- 备忘录模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter18.md) -------------------------------------------------------------------------------- /files/chapter18.md: -------------------------------------------------------------------------------- 1 | ### 第十八章 如果再回到从前 --- 备忘录模式 2 | 3 | ```php 4 | state = $state; 14 | } 15 | public function getState() 16 | { 17 | return $this->state; 18 | } 19 | 20 | //创建备忘录,将当前需要保存的信息导入并实例化出一个memento对象。 21 | public function createMemento() 22 | { 23 | return new Memento($this->state); 24 | } 25 | 26 | //恢复备忘录,将memento导入并将相关数据恢复。 27 | public function setMemento(Memento $memento) 28 | { 29 | $this->state = $memento->getState(); 30 | } 31 | 32 | //显示数据 33 | public function show() 34 | { 35 | echo "status ".$this->state."\n"; 36 | } 37 | } 38 | 39 | //备忘录类 40 | 41 | class Memento 42 | { 43 | private $state; 44 | 45 | //构造方法,将相关数据导入 46 | function __construct($state) 47 | { 48 | $this->state = $state; 49 | } 50 | 51 | //获取需要保存的数据,可以多个 52 | public function getState() 53 | { 54 | return $this->state; 55 | } 56 | } 57 | 58 | //管理者类 59 | class CareTaker 60 | { 61 | private $memento; 62 | 63 | public function getMemento() 64 | { 65 | return $this->memento; 66 | } 67 | 68 | //设置备忘录 69 | public function setMemento(Memento $memento) 70 | { 71 | $this->memento = $memento; 72 | } 73 | } 74 | 75 | //客户端程序 76 | $o = new Originator(); //Originator初始状态,状态属性on 77 | $o->setState("On"); 78 | $o->show(); 79 | 80 | //保存状态时,由于有了很好的封装,可以隐藏Originator的实现细节 81 | $c = new CareTaker(); 82 | $c->setMemento($o->createMemento()); 83 | 84 | // 改变属性 85 | $o->setState("Off"); 86 | $o->show(); 87 | 88 | // 恢复属性 89 | $o->setMemento($c->getMemento()); 90 | $o->show(); 91 | ``` 92 | 93 | 总结: 94 | 95 | > ***备忘录模式***,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之前保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 96 | 97 | > 代码无措未必优 98 | 99 | > 如果在某个系统中使用命令模式时,需要实现命令的撤销功能,那么命令模式可以使用备忘录模式来存储可撤销操作的状态。 100 | 101 | > 使用备忘录可以把复杂的对象内部信息对其他的对象屏蔽起来。 102 | 103 | 104 | 上一章:[第十七章 在NBA我需要翻译 --- 适配器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter17.md) 105 | 106 | 下一章:[第十九章 分公司 = 一部分 --- 组合模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter19.md) -------------------------------------------------------------------------------- /files/chapter19.md: -------------------------------------------------------------------------------- 1 | ### 第十九章 分公司 = 一部分 --- 组合模式 2 | ```php 3 | name = $name; 13 | } 14 | 15 | //通常用add和remove方法来提供增加或移除树枝货树叶的功能 16 | abstract public function add(Component $c); 17 | abstract public function remove(Component $c); 18 | abstract public function display($depth); 19 | } 20 | 21 | //leaf在组合中表示叶节点对象,叶节点对象没有子节点。 22 | class Leaf extends Component 23 | { 24 | // 由于叶子没有再增加分枝和树叶,所以add和remove方法实现它没有意义, 25 | // 但这样做可以消除叶节点和枝节点对象在抽象层次的区别,它们具有完全一致的接口 26 | public function add(Component $c) 27 | { 28 | echo "can not add to a leaf\n"; 29 | } 30 | 31 | public function remove(Component $c) 32 | { 33 | echo "can not remove to a leaf\n"; 34 | } 35 | 36 | // 叶节点的具体方法,此处是显示其名称和级别 37 | public function display($depth) 38 | { 39 | echo str_repeat('-', $depth).$this->name."\n"; 40 | } 41 | } 42 | 43 | //composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加add和删除remove. 44 | 45 | class Composite extends Component 46 | { 47 | //一个子对象集合用来存储其下属的枝节点和叶节点。 48 | private $childern = []; 49 | 50 | public function add(Component $c) 51 | { 52 | array_push($this->childern, $c); 53 | } 54 | 55 | public function remove(Component $c) 56 | { 57 | foreach ($this->childern as $key => $value) { 58 | if ($c === $value) { 59 | unset($this->childern[$key]); 60 | } 61 | } 62 | } 63 | 64 | // 显示其枝节点名称,并对其下级进行遍历 65 | public function display($depth) 66 | { 67 | echo str_repeat('-', $depth).$this->name."\n"; 68 | foreach ($this->childern as $component) { 69 | $component->display($depth + 2); 70 | } 71 | } 72 | } 73 | 74 | //客户端代码 75 | 76 | $root = new Composite('root'); 77 | $root->add(new Leaf("Leaf A")); 78 | $root->add(new Leaf("Leaf B")); 79 | 80 | $comp = new Composite("Composite X"); 81 | $comp->add(new Leaf("Leaf XA")); 82 | $comp->add(new Leaf("Leaf XB")); 83 | 84 | $root->add($comp); 85 | 86 | $comp2 = new Composite("Composite X"); 87 | $comp2->add(new Leaf("Leaf XA")); 88 | $comp2->add(new Leaf("Leaf XB")); 89 | 90 | $comp->add($comp2); 91 | 92 | $root->add(new Leaf("Leaf C")); 93 | 94 | $leaf = new Leaf("Leaf D"); 95 | $root->add($leaf); 96 | $root->remove($leaf); 97 | 98 | $root->display(1); 99 | ``` 100 | 101 | 总结: 102 | 103 | > ***组合模式***,将对象组合成树形结构以表示‘部分与整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。 104 | 105 | > 透明方式,子类的所有接口一致,虽然有些接口没有用。 106 | 107 | > 安全方式,子类接口不一致,只实现特定的接口,但是这样就要做相应的判断,带来了不便。 108 | 109 | > 需求中是体现部分与整体层次的结构时,或希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了。 110 | 111 | > 组合模式可以让客户一致地使用组合结构和单个对象。 112 | 113 | 上一章:[第十八章 如果再回到从前 --- 备忘录模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter18.md) 114 | 115 | 下一章:[第二十章 想走?可以!先买票 --- 迭代器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter20.md) -------------------------------------------------------------------------------- /files/chapter2.md: -------------------------------------------------------------------------------- 1 | ### 第二章 商场促销 --- 策略模式 2 | 3 | 1.策略模式 4 | ```php 5 | strategy = $strategy; 60 | } 61 | 62 | public function contextInterface() 63 | { 64 | $this->strategy->AlgorithmInterface(); 65 | } 66 | } 67 | 68 | $context = new Context(new ConcreteStrategyA()); 69 | $context->contextInterface(); 70 | 71 | $context = new Context(new ConcreteStrategyB()); 72 | $context->contextInterface(); 73 | 74 | $context = new Context(new ConcreteStrategyC()); 75 | $context->contextInterface(); 76 | 77 | 78 | ``` 79 | 80 | 2.策略模式和简单工厂结合 81 | ```php 82 | strategy = new ConcreteStrategyA(); 94 | break; 95 | case 'b': 96 | $this->strategy = new ConcreteStrategyB(); 97 | break; 98 | case 'c': 99 | $this->strategy = new ConcreteStrategyC(); 100 | break; 101 | } 102 | } 103 | 104 | public function contextInterface() 105 | { 106 | return $this->strategy->AlgorithmInterface(); 107 | } 108 | } 109 | 110 | //客户端代码 111 | $context = new Context('a'); 112 | $context->contextInterface(); 113 | ``` 114 | 115 | 总结: 116 | > 面向对象的编程,并不是类越多越好,类的划分为了封装,但分类的基础是抽象,具有相同属性和功能的对象集合才是类。 117 | 118 | > 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。 119 | 120 | > 策略模式的Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中公共功能。 121 | 122 | > 策略模式简化了单元测试,因为每个算法都有自己的类,可以通自己接口单独测试。 123 | 124 | > 当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为。将这些行为封装在一个个Strategy类中,可以在使用这些行为的类中消除条件语句。 125 | 126 | > 策略模式就是用来封装算法的,但在实践中,我们发现可以用它来封装几乎任何类型的规则,只要在分析过程中听到需要在不同时间应用不同的业务规则,就可以考虑使用策略模式处理这种变化的可能性。 127 | 128 | > 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。 129 | 130 | 上一章:[第一章 代码无错就是优 ---简单工厂模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter1.md) 131 | 132 | 下一章:[第三章 拍摄UFO --- 单一职责原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter3.md) 133 | -------------------------------------------------------------------------------- /files/chapter20.md: -------------------------------------------------------------------------------- 1 | ### 第二十章 想走?可以!先买票 --- 迭代器模式 2 | 3 | ```php 4 | aggregate = $aggregate; 28 | } 29 | 30 | public function first() 31 | { 32 | return $this->aggregate[0]; 33 | } 34 | 35 | public function next() 36 | { 37 | $ret = null; 38 | $this->current++; 39 | if ($this->current < count($this->aggregate)) 40 | { 41 | $ret = $this->aggregate[$this->current]; 42 | } 43 | return $ret; 44 | } 45 | 46 | public function isDone() 47 | { 48 | return $this->current >= count($this->aggregate); 49 | } 50 | 51 | public function currentItem() 52 | { 53 | return $this->aggregate[$this->current]; 54 | } 55 | } 56 | 57 | //这个类的代码感觉不符合书上的写法,但我感觉书上的不对,可能我知识面太单薄,没读懂,可自行参阅原著😊。 58 | class ConcreteAggregate extends Aggregate 59 | { 60 | private $items = []; 61 | 62 | public function createIterator() 63 | { 64 | return new ConcreteIterator($this); 65 | } 66 | 67 | public function count() 68 | { 69 | return count($this->items); 70 | } 71 | 72 | public function add($item) 73 | { 74 | array_push($this->items, $item); 75 | } 76 | 77 | public function items() 78 | { 79 | return $this->items; 80 | } 81 | } 82 | 83 | //客户端代码 84 | $a = new ConcreteAggregate(); 85 | $a->add("大鸟"); 86 | $a->add("小菜"); 87 | $a->add("行李"); 88 | $a->add("老外"); 89 | $a->add("公交内部员工"); 90 | $a->add("小偷"); 91 | 92 | $i = new ConcreteIterator($a->items()); 93 | 94 | while (!$i->isDone()) 95 | { 96 | echo $i->currentItem()." 请买票\n"; 97 | $i->next(); 98 | } 99 | ``` 100 | 101 | 总结: 102 | 103 | > 当你需要对聚集有多种方式遍历时,可以考虑用迭代器模式。 104 | 105 | > 当你需要访问一个聚集对象,而且不管这些对象是什么都需要遍历的时候,你就应该考虑用迭代器模式。 106 | 107 | > 为遍历不同的聚集结构提供如开始、下一个、是否结束、当前哪一项等统一的接口。 108 | 109 | > 迭代器模式就是分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合内部的结构,又可让外部代码透明地访问集合内部的数据。 110 | 111 | 112 | 上一章:[第十九章 分公司 = 一部分 --- 组合模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter19.md) 113 | 114 | 下一章:[第二十一章 有些类也需要计划生育 --- 单例模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter21.md) -------------------------------------------------------------------------------- /files/chapter21.md: -------------------------------------------------------------------------------- 1 | ### 第二十一章 有些类也需要计划生育 --- 单例模式 2 | 3 | ```php 4 | ***单例模式***,保证一个类仅有一个实例,并提供一个访问它的全局访问点。 37 | 38 | > 单例模式因为Singleton类封装它的唯一实例,这样它可以严格地控制客户怎样访问以及何时访问它。简单地说就是对唯一实例的受控访问。 39 | 40 | 41 | 上一章:[第二十章 想走?可以!先买票 --- 迭代器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter20.md) 42 | 43 | 下一章:[第二十二章 手机软件何时统一 --- 桥接模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter22.md) 44 | -------------------------------------------------------------------------------- /files/chapter22.md: -------------------------------------------------------------------------------- 1 | ### 第二十二章 手机软件何时统一 --- 桥接模式 2 | 3 | ```php 4 | soft = $soft; 40 | } 41 | 42 | //运行 43 | abstract public function run(); 44 | } 45 | 46 | // 手机品牌n 47 | class HandsetBrandN extends HandsetBrand 48 | { 49 | public function run() 50 | { 51 | $this->soft->run(); 52 | } 53 | } 54 | 55 | // 手机品牌m 56 | class HandsetBrandM extends HandsetBrand 57 | { 58 | public function run() 59 | { 60 | $this->soft->run(); 61 | } 62 | } 63 | 64 | //客户端调用代码 65 | $ab = new HandsetBrandN(); 66 | $ab->setHandsetSoft(new HandsetGame()); 67 | $ab->run(); 68 | 69 | $ab->setHandsetSoft(new HandsetAddressList()); 70 | $ab->run(); 71 | 72 | $ab = new HandsetBrandM(); 73 | $ab->setHandsetSoft(new HandsetGame()); 74 | $ab->run(); 75 | 76 | $ab->setHandsetSoft(new HandsetAddressList()); 77 | $ab->run(); 78 | ``` 79 | 80 | 总结: 81 | 82 | > 桥接模式,将抽象部分与它的实现部分分离,使它们都可以独立地变化。 83 | 84 | > 合成/聚合复用原则,尽量使用合成/聚合,尽量不要使用类继承。 85 | 86 | > 聚合表示弱的‘拥有’关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;合成则是一种强的‘拥有’关系,体现了严格的部分和整体的关系,部分和整体的生命周期一样。 87 | 88 | > 对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当你需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更合适的类替换。这种依赖关系限制了灵活性并最终限制了复用性。 89 | 90 | > 优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。 91 | 92 | > 什么叫抽象与它的实现分离,这并不是说,让抽象类与其派生类分离,因为这没有任何意义。实现指的是抽象类和它的派生类用来实现自己的对象。 93 | 94 | > 实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。 95 | 96 | > 只要真正深入地理解了设计原则,很多设计模式其实就是原则的应用而已,或许在不知不觉中就在使用设计模式了。 97 | 98 | 上一章:[第二十一章 有些类也需要计划生育 --- 单例模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter21.md) 99 | 100 | 下一章:[第二十三章 烤羊肉串引来的思考 --- 命令模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter23.md) -------------------------------------------------------------------------------- /files/chapter23.md: -------------------------------------------------------------------------------- 1 | ### 第二十三章 烤羊肉串引来的思考 --- 命令模式 2 | 3 | ```php 4 | receiver = $receiver; 29 | } 30 | 31 | abstract public function excuteCommand(); 32 | } 33 | 34 | //烤羊肉 35 | class BakeMuttonCommand extends Command 36 | { 37 | public function excuteCommand() 38 | { 39 | $this->receiver->bakeMutton(); 40 | } 41 | } 42 | 43 | //烤鸡翅 44 | class BakeChickenWingCommand extends Command 45 | { 46 | public function excuteCommand() 47 | { 48 | $this->receiver->bakeChickenWing(); 49 | } 50 | } 51 | 52 | //服务员 53 | class Waiter 54 | { 55 | private $commands = []; 56 | 57 | //设置订单 58 | public function setOrder(Command $command) 59 | { 60 | if ($command instanceof BakeChickenWingCommand) 61 | { 62 | echo "服务员: 鸡翅没有了,请点别的烧烤\n"; 63 | } else { 64 | echo "增加订单\n"; 65 | array_push($this->commands, $command); 66 | } 67 | } 68 | 69 | //取消订单 70 | public function cancelOrder(Command $command){} 71 | 72 | //通知执行 73 | public function notify() 74 | { 75 | foreach ($this->commands as $value) { 76 | $value->excuteCommand(); 77 | } 78 | } 79 | } 80 | 81 | //客户端代码 82 | 83 | //开店前准备 84 | $boy = new Barbecuer(); 85 | $bakeMuttonCommand1 = new BakeMuttonCommand($boy); 86 | $bakeMuttonCommand2 = new BakeMuttonCommand($boy); 87 | $bakeChickenWingCommand1 = new BakeChickenWingCommand($boy); 88 | $girl = new Waiter(); 89 | 90 | //开门营业 91 | $girl->setOrder($bakeMuttonCommand1); 92 | $girl->setOrder($bakeMuttonCommand2); 93 | $girl->setOrder($bakeChickenWingCommand1); 94 | $girl->notify(); 95 | ``` 96 | 97 | 总结: 98 | 99 | > ***命令模式***,将 一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 100 | 101 | > 对请求派对或记录请求日志,以及日志可撤销的操作。 102 | 103 | > 优点:第一,能较容易地设计一个命令队列;第二,在需要的情况下,可以较容易地将命令记入日志;第三,允许请求的一方决定是否要否决请求;第四,可以容易地实现对请求的撤销和重做;第五,由于加进新的具体命令类不影响其他的类,因此增加新的具体命令类很容易;最重要的是该 模式把请求一个操作的对象与知道怎么执行一个操作的对象分隔开。 104 | 105 | > 敏捷开发原则告诉我们,不要为代码添加基于猜测的、实际不需要的功能。如果不清楚一个系统是否需要命令模式,一般酒不要急着去实现它,事实上,在需要的时候通过重构实现这个模式并不难,只有在真正需要如撤销/恢复操作等功能时,把原来的代码重构为命令模式才有意义。 106 | 107 | 上一章:[第二十二章 手机软件何时统一 --- 桥接模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter22.md) 108 | 109 | 下一章:[第二十四章 加薪非要老总批 --- 职责链模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter24.md) -------------------------------------------------------------------------------- /files/chapter24.md: -------------------------------------------------------------------------------- 1 | ### 第二十四章 加薪非要老总批 --- 职责链模式 2 | ```php 3 | abstract class Handler 4 | { 5 | protected $successor; 6 | 7 | //设置继承者 8 | public function setSuccessor(Handler $successor) 9 | { 10 | $this->successor = $successor; 11 | } 12 | 13 | //处理请求的抽象方法 14 | abstract function handleRequest(int $request); 15 | } 16 | 17 | //如果可以处理请求,就处理之,否者转发给它的后继者 18 | class ConcreteHandler1 extends Handler 19 | { 20 | public function handleRequest(int $request) 21 | { 22 | if ($request >=0 && $request < 10) 23 | { 24 | echo "ConcreteHandler1 handle it\n"; 25 | } else if ($this->successor != null) { 26 | // 转移 27 | $this->successor->handleRequest($request); 28 | } 29 | } 30 | } 31 | 32 | class ConcreteHandler2 extends Handler 33 | { 34 | public function handleRequest(int $request) 35 | { 36 | if ($request >=10 && $request < 20) 37 | { 38 | echo "ConcreteHandler2 handle it\n"; 39 | } else if ($this->successor != null) { 40 | $this->successor->handleRequest($request); 41 | } 42 | } 43 | } 44 | 45 | // client 46 | $h1 = new ConcreteHandler1(); 47 | $h2 = new ConcreteHandler2(); 48 | 设置职责链上下家 49 | $h1->setSuccessor($h2); 50 | $requests = [1,5,7,16,25]; 51 | 循环给最小处理者提交请求,不同的数额,由不同权限处理者处理 52 | foreach ($requests as $value) { 53 | $h1->handleRequest($value); 54 | } 55 | ``` 56 | 57 | 总结 58 | > ***职责链模式***, 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对像处理它为止。 59 | 60 | > 当用户提交一个请求时,请求是沿着链传递直至有一个对象负责处理它。 61 | 62 | > 接受者和发送者都没有对方的明确信息,且链中的对象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅需要保持一个向其后继者的引用,而不需要保持它所有的候选者的引用。 63 | 64 | > 随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。 65 | 66 | > 一个请求极有可能到了链的末端都得不到处理,或者因为没有正确配置而得不到处理。 67 | 68 | 上一章:[第二十三章 烤羊肉串引来的思考 --- 命令模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter23.md) 69 | 70 | 下一章:[第二十五章 世界需要和平 --- 中介者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter25.md) -------------------------------------------------------------------------------- /files/chapter25.md: -------------------------------------------------------------------------------- 1 | ### 第二十五章 世界需要和平 --- 中介者模式 2 | 3 | ```php 4 | mediator = $mediator; 18 | } 19 | } 20 | 21 | class ConcreteMediator extends Mediator 22 | { 23 | private $colleague1; 24 | private $colleague2; 25 | 26 | public function setColleague1(Colleague $colleague) 27 | { 28 | $this->colleague1 = $colleague; 29 | } 30 | 31 | public function setColleague2(Colleague $colleague) 32 | { 33 | $this->colleague2 = $colleague; 34 | } 35 | 36 | public function send($message, Colleague $colleague) 37 | { 38 | if($this->colleague1 == $colleague) 39 | { 40 | $this->colleague2->notify($message); 41 | } else { 42 | $this->colleague1->notify($message); 43 | } 44 | } 45 | } 46 | 47 | class ConcreteColleague1 extends Colleague 48 | { 49 | public function send($message) 50 | { 51 | $this->mediator->send($message, $this); 52 | } 53 | 54 | public function notify($message) 55 | { 56 | echo "ConcreteColleague1 ".$message."\n"; 57 | } 58 | } 59 | 60 | class ConcreteColleague2 extends Colleague 61 | { 62 | public function send($message) 63 | { 64 | $this->mediator->send($message, $this); 65 | } 66 | 67 | public function notify($message) 68 | { 69 | echo "ConcreteColleague2 ".$message."\n";; 70 | } 71 | } 72 | 73 | //client 74 | 75 | $mediator = new ConcreteMediator(); 76 | $c1 = new ConcreteColleague1($mediator); 77 | $c2 = new ConcreteColleague2($mediator); 78 | 79 | $mediator->setColleague1($c1); 80 | $mediator->setColleague2($c2); 81 | 82 | $c1->send('do you eat?'); 83 | $c2->send('no, do you want to invite me to dinner?'); 84 | ``` 85 | 86 | 总结 87 | 88 | > ***中介者模式***,用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互交互,从而使其耦合松散,而且可以独立地改变它们之间的交互。 89 | 90 | > 尽管将一个系统分割成许多对象通常可以增加其可复用性,但是对象间的交互连接的激增又会降低其可复用性了。 91 | 92 | > 大量的连接使得一个对象不大可能在没有其他对象的支持下工作,系统表现为一个不可分割的整体,所以,对系统的行为进行任何较大的改动就十分困难了。 93 | 94 | > 中介者模式很容易在系统中应用,也很容易在系统中误用。当系统出现了‘多对多’交互复杂的对象群时,不要急于使用中介者模式,而要反思你的系统设计上是不是合理。 95 | 96 | > 由于把对象如何协作进行了抽象,将中介作为一个独立的概念并将其封装在一个对象中,这样关注的对象就从对象各自本身的行为转移到它们之间的交互上来,也就是站在一个更宏观的角度去看待系统。 97 | 98 | > 中介者模式一般应用于一组对象以定义良好但是复杂的方式进行通信的结合,以及想定制一个分布在多个类中的行为,而又不想生成太多的子类的场合。 99 | 100 | 上一章:[第二十四章 加薪非要老总批 --- 职责链模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter24.md) 101 | 102 | 下一章:[第二十六章 项目多也别傻做 --- 享元模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter26.md) -------------------------------------------------------------------------------- /files/chapter26.md: -------------------------------------------------------------------------------- 1 | ### 第二十六章 项目多也别傻做 --- 享元模式 2 | 3 | ```php 4 | class User 5 | { 6 | private $name; 7 | function __construct($name) 8 | { 9 | $this->name = $name; 10 | } 11 | 12 | public function getName() 13 | { 14 | return $this->name; 15 | } 16 | } 17 | 18 | abstract class WebSite 19 | { 20 | abstract public function use(User $user); 21 | } 22 | 23 | // 具体网站类 24 | class ConcreteWebSite extends WebSite 25 | { 26 | private $name = ''; 27 | 28 | function __construct($name) 29 | { 30 | $this->name = $name; 31 | } 32 | 33 | public function use(User $user) 34 | { 35 | echo "网站分类: ".$this->name."用户:".$user->getName()."\n"; 36 | } 37 | } 38 | 39 | //网站工厂 40 | class WebSiteFactory 41 | { 42 | private $flyweights = []; 43 | 44 | public function getWebSiteGategory($key) 45 | { 46 | if (empty($this->flyweights[$key])) { 47 | $this->flyweights[$key] = new ConcreteWebSite($key); 48 | } 49 | return $this->flyweights[$key]; 50 | } 51 | 52 | 53 | public function getWebSiteCount() 54 | { 55 | return count($this->flyweights); 56 | } 57 | } 58 | 59 | $f = new WebSiteFactory(); 60 | $fx = $f->getWebSiteGategory('产品展示'); 61 | $fx->use(new User('张伟')); 62 | 63 | $fy = $f->getWebSiteGategory('产品展示'); 64 | $fy->use(new User('王伟')); 65 | 66 | $fz = $f->getWebSiteGategory('产品展示'); 67 | $fz->use(new User('王芳')); 68 | 69 | $fl = $f->getWebSiteGategory('博客'); 70 | $fl->use(new User('李伟')); 71 | 72 | $fm = $f->getWebSiteGategory('博客'); 73 | $fm->use(new User('王秀英')); 74 | 75 | $fn = $f->getWebSiteGategory('博客'); 76 | $fn->use(new User('李秀英')); 77 | 78 | echo "网站分类总数:".$f->getWebSiteCount()."\n"; 79 | ``` 80 | 81 | 总结 82 | 83 | > ***享原模式*** 运用共享技术有效地支持大量细粒度的对象 84 | 85 | > 享原模式可以避免大量非常类似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。 86 | 87 | > 如果一个应用程序使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用;还有就是对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象,此时可以考虑使用享原模式。 88 | 89 | 上一章:[第二十五章 世界需要和平 --- 中介者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter25.md) 90 | 91 | 下一章:[第二十七章 其实你不懂老板的心 --- 解释器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter27.md) -------------------------------------------------------------------------------- /files/chapter27.md: -------------------------------------------------------------------------------- 1 | ### 第二十七章 其实你不懂老板的心 --- 解释器模式 2 | 3 | ```php 4 | input = $input; 33 | } 34 | 35 | public function getInput() 36 | { 37 | return $this->input; 38 | } 39 | 40 | private $output; 41 | public function setOutput($output) 42 | { 43 | $this->output = $output; 44 | } 45 | 46 | public function getOutput() 47 | { 48 | return $this->output; 49 | } 50 | } 51 | 52 | 53 | $context = new Context(); 54 | $syntax = []; 55 | array_push($syntax, new TerminalExpression()); 56 | array_push($syntax, new NonTerminalExpression()); 57 | array_push($syntax, new TerminalExpression()); 58 | array_push($syntax, new TerminalExpression()); 59 | 60 | foreach ($syntax as $value) { 61 | $value->interpret($context); 62 | } 63 | ``` 64 | 65 | > ***解释器模式***,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言的句子。 66 | 67 | > 如果一种特定语言类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。 68 | 69 | > 通常当有一个语言需要解释执行,并且你可将该语言的句子表示为一个抽象语法树时,可使用解释器模式。 70 | 71 | > 解释器模式容易修改和扩展文法,因为解释器模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。 72 | 73 | > 解释器模式不足的是要为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。 74 | 75 | 上一章:[第二十六章 项目多也别傻做 --- 享元模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter26.md) 76 | 77 | 下一章:[第二十八章 男人和女人 --- 访问者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter28.md) -------------------------------------------------------------------------------- /files/chapter28.md: -------------------------------------------------------------------------------- 1 | ### 第二十八章 男人和女人 --- 访问者模式 2 | 3 | ```php 4 | getManConclusion($this); 62 | } 63 | } 64 | 65 | class Woman extends Person 66 | { 67 | public function accept(Action $visitor) 68 | { 69 | $visitor->getWomanConclusion($this); 70 | } 71 | } 72 | 73 | class ObjectStructure 74 | { 75 | private $person = []; 76 | 77 | public function acctch(Person $person) 78 | { 79 | array_push($this->person, $person); 80 | } 81 | 82 | public function display(Action $visitor) 83 | { 84 | foreach ($this->person as $person) { 85 | $person->accept($visitor); 86 | } 87 | } 88 | } 89 | 90 | 91 | $o = new ObjectStructure(); 92 | $o->acctch(new Man()); 93 | $o->acctch(new Woman()); 94 | 95 | // 成功时的反应 96 | $v1 = new Success(); 97 | $o->display($v1); 98 | 99 | 100 | $v2 = new Failing(); 101 | $o->display($v2); 102 | 103 | 104 | $v3 = new Amativeness(); 105 | $o->display($v3); 106 | ``` 107 | 108 | 总结 109 | 110 | > ***访问者模式***,表示一个作用于某对象结构中的各个元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 111 | 112 | > 访问者模式适合用于数据结构相对稳定的系统。它把数据结构和作用于结构上的操作之间的耦合解脱开,使得操作集合可以相对自由地演化。 113 | 114 | > 访问者的目的是要把处理从数据结构分离出来。这样系统有比较稳定的数据结构,又有易于变化的算法的话,使用访问者模式就是比较合适的,因为访问者模式使得算法操作的增加变得容易。 115 | 116 | > 增加新的操作容易,因为增加新的操作就意味着增加一个新的访问者。访问者将有关行为集中到一个访问者对象中。 117 | 118 | > 访问者模式使增加新的数据结构变得困难了。 119 | 120 | 121 | 122 | 123 | 上一章:[第二十七章 其实你不懂老板的心 --- 解释器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter27.md) 124 | 125 | 下一章:[第二十九章 OOTV杯超级模式大赛 --- 模式总结](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter29.md) -------------------------------------------------------------------------------- /files/chapter29.md: -------------------------------------------------------------------------------- 1 | ### 第二十九章 OOTV杯超级模式大赛 --- 模式总结 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 | 上一章:[第二十八章 男人和女人 --- 访问者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter28.md) -------------------------------------------------------------------------------- /files/chapter3.md: -------------------------------------------------------------------------------- 1 | ### 第三章 拍摄UFO --- 单一职责原则 2 | 3 | 总结 4 | 5 | > ***单一职责原则***, 就一个类而言,应该仅有一个引起 它变化的原因。 6 | 7 | >如果一个类承担的职责过多,就等于把职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破环。 8 | 9 | >软件设计真正要做的许多内容,就是发现职责并把这些职责相互分离。 10 | 11 | > 如果你能够想到多于一个的动机改变一个类,那么这个类就具有多于一个类的职责。 12 | 13 | 上一章:[第二章 商场促销 --- 策略模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter2.md) 14 | 15 | 下一章:[第四章 考研求职两不误 --- 开放-封闭原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter4.md) -------------------------------------------------------------------------------- /files/chapter4.md: -------------------------------------------------------------------------------- 1 | ### 第四章 研求职两不误 --- 开放-封闭原则 2 | 3 | 总结 4 | > ***开放-封闭原则***, 是说软件实体应该可以扩展,但是不可以修改。 5 | 6 | > 怎样的设计才能面对需求的改变却可以保持相对稳定,从而使得系统可以在第一个版本以后不断推出新的版本呢? 7 | 8 | > 无论模块是多么的‘封闭’,都会存在一些无法对之封闭的变化。既然不可能完全封闭,设计人员必须对于他设计的模块应该对哪种变化封闭做出选择。他必须先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化。 9 | 10 | > 等到发生变化时立即采取行动。 11 | 12 | > 在我们最初编写代码时,假设变化不会发生。当发生变化时,我们就创建抽象来隔离以后发生的同类变化。 13 | 14 | > 面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码。 15 | 16 | > 开发-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护,可复用,灵活性好。开发人员应该仅对程序中呈现出频繁变化的那些部分做出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一件好事。拒绝不成熟的抽象和抽象本身一样重要。 17 | 18 | 19 | 20 | 上一章:[第三章 拍摄UFO --- 单一职责原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter3.md) 21 | 22 | 下一章:[第五章 会修电脑不会修收音机? --- 依赖倒转原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter5.md) -------------------------------------------------------------------------------- /files/chapter5.md: -------------------------------------------------------------------------------- 1 | ### 第五章 会修电脑不会修收音机? --- 依赖倒转原则 2 | 3 | 总结 4 | > ***依赖倒转原则***, 高层模块不应该依赖底层模块,抽象不应该依赖细节,都应该依赖抽象。针对接口编程,不要对实现编程。 5 | 6 | > ***里氏替换原则***,子类型必须能够替换它们的父类型。 7 | 8 | > 只有当子类可以替换父类,软件单位的功能不受影响时,父类才真正被复用,而子类也能够在父类的基础上增加新的行为。 9 | 10 | > 由于子类型的可替换性才使得使用父类类型的模块在无需修改的情况下就可以扩展。 11 | 12 | > 依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。 13 | 14 | 上一章:[第四章 研求职两不误 --- 开放-封闭原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter4.md) 15 | 16 | 下一章:[第六章 穿什么有这么重要吗 --- 装饰模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter6.md) -------------------------------------------------------------------------------- /files/chapter7.md: -------------------------------------------------------------------------------- 1 | ### 第七章 为别人做嫁衣 --- 代理模式 2 | 3 | ```php 4 | name = $name; 13 | } 14 | 15 | public function getName() 16 | { 17 | return $this->name; 18 | } 19 | } 20 | 21 | // 代理接口 22 | interface GiveGift 23 | { 24 | public function GiveDolls(); 25 | public function GiveFlowers(); 26 | public function GiveChocolate(); 27 | } 28 | 29 | // 代理实现送礼物接口 30 | class Proxy implements GiveGift 31 | { 32 | protected $pursuit; 33 | 34 | function __construct(SchoolGirl $girl) 35 | { 36 | $this->pursuit = new Pursuit($girl); 37 | } 38 | 39 | public function GiveDolls() 40 | { 41 | $this->pursuit->GiveDolls(); 42 | } 43 | 44 | public function GiveFlowers() 45 | { 46 | $this->pursuit->GiveFlowers(); 47 | } 48 | 49 | public function GiveChocolate() 50 | { 51 | $this->pursuit->GiveChocolate(); 52 | } 53 | } 54 | 55 | // 追求者类实现送礼物接口 56 | class Pursuit implements GiveGift 57 | { 58 | protected $girl; 59 | function __construct(SchoolGirl $girl) 60 | { 61 | $this->girl = $girl; 62 | } 63 | 64 | public function GiveDolls() 65 | { 66 | echo $this->girl->getName()." 送你娃娃\n"; 67 | } 68 | 69 | public function GiveFlowers() 70 | { 71 | echo $this->girl->getName()." 送你花\n"; 72 | } 73 | 74 | public function GiveChocolate() 75 | { 76 | echo $this->girl->getName()." 送你巧克力\n"; 77 | } 78 | } 79 | 80 | // 客户端代码 81 | $girl = new SchoolGirl('李梅'); 82 | $proxy = new Proxy($girl); 83 | $proxy->GiveDolls(); 84 | $proxy->GiveChocolate(); 85 | $proxy->GiveFlowers(); 86 | 87 | ``` 88 | 89 | 总结: 90 | > ***代理模式***,为其他对象提供一种代理以控制对这个对象的访问 91 | 92 | 上一章:[第六章 穿什么有这么重要吗 --- 装饰模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter6.md) 93 | 94 | 下一章:[第八章 雷锋依然在人间 --- 工厂方法模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter8.md) -------------------------------------------------------------------------------- /files/chapter8.md: -------------------------------------------------------------------------------- 1 | ### 第八章 雷锋依然在人间 --- 工厂方法模式 2 | 3 | 根据[第一章](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter1.md),简单工厂模式(加减乘除)是这样的: 4 | ```php 5 | class OperationFactory 6 | { 7 | public static function createOperation($operation) 8 | { 9 | switch ($operation) { 10 | case '+': 11 | $oper = new OperationAdd(); 12 | break; 13 | case '-': 14 | $oper = new OperationSub(); 15 | break; 16 | case '/': 17 | $oper = new OperationDiv(); 18 | break; 19 | case '*': 20 | $oper = new OperationMul(); 21 | break; 22 | } 23 | return $oper; 24 | } 25 | } 26 | // 客户端代码 27 | $operation = OperationFactory::createOperation('+'); 28 | $operation->setA(1); 29 | $operation->setA(2); 30 | echo $operation->getResult()."\n"; 31 | ``` 32 | 换成工厂方法模式 33 | ```php 34 | interface IFactory 35 | { 36 | public function CreateOperation(); 37 | } 38 | 39 | class AddFactory implements IFactory 40 | { 41 | public function CreateOperation() 42 | { 43 | return new OperationAdd(); 44 | } 45 | } 46 | 47 | class SubFactory implements IFactory 48 | { 49 | public function CreateOperation() 50 | { 51 | return new OperationSub(); 52 | } 53 | } 54 | 55 | class MulFactory implements IFactory 56 | { 57 | public function CreateOperation() 58 | { 59 | return new OperationMul(); 60 | } 61 | } 62 | 63 | class DivFactory implements IFactory 64 | { 65 | public function CreateOperation() 66 | { 67 | return new OperationDiv(); 68 | } 69 | } 70 | 71 | //客户端代码 72 | $operationFactory = new AddFactory(); 73 | $operation = $operationFactory->CreateOperation(); 74 | $operation->setA(10); 75 | $operation->setB(10); 76 | echo $operation->getResult()."\n"; 77 | ``` 78 | 79 | 80 | 总结: 81 | 82 | > ***工厂方法模式***,定义一个创建对象的接口,让子类确定实例化哪一个类。工厂方法使一个类的实例化延迟到7其子类。 83 | 84 | > 简单工厂模式的最大优点在于工厂类中包含了必要的逻辑判断,根据用户端的选择条件动态实例化相关的类,对于客户端来说,去除了与具体产品的依赖。 85 | 86 | > 工厂方法模式实现时,客户端需要决定实例化哪一个工厂来实现运算类,选择判断的问题还是存在的,也就是说,工厂方法把简单工厂的内部逻辑判断移到了客户端代码来进行。你 想要加功能,本来是改工厂类的,而现在是修改客户端。 87 | 88 | 上一章:[第七章 为别人做嫁衣 --- 代理模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter7.md) 89 | 90 | 下一章:[第九章 简历复印 --- 原型模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter9.md) -------------------------------------------------------------------------------- /files/chapter9.md: -------------------------------------------------------------------------------- 1 | ### 第九章 简历复印 --- 原型模式 2 | 3 | ```php 4 | company = $name; 13 | } 14 | 15 | public function getName() 16 | { 17 | return $this->company; 18 | } 19 | } 20 | 21 | class Resume 22 | { 23 | private $name; 24 | private $sex; 25 | private $age; 26 | private $timeArea; 27 | private $company; 28 | 29 | function __construct($name) 30 | { 31 | $this->name = $name; 32 | $this->company = new Company(); 33 | } 34 | 35 | public function setPersonalInfo($sex, $age) 36 | { 37 | $this->sex = $sex; 38 | $this->age = $age; 39 | } 40 | 41 | public function setWorkExperience($timeArea, $company) 42 | { 43 | $this->timeArea = $timeArea; 44 | $this->company->setName($company); 45 | } 46 | 47 | public function display() 48 | { 49 | echo $this->name." ".$this->sex." ".$this->age."\n"; 50 | echo $this->timeArea." ".$this->company->getName()."\n"; 51 | } 52 | 53 | // 对引用执行深复制 54 | function __clone() 55 | { 56 | $this->company = clone $this->company; 57 | } 58 | } 59 | 60 | // 客户端代码 61 | $resume = new Resume("大鸟"); 62 | $resume->setPersonalInfo("男", 29); 63 | $resume->setWorkExperience("1998-2000","xxx 公司"); 64 | 65 | $resume2 = clone $resume; 66 | $resume2->setPersonalInfo("男", 40); 67 | $resume2->setWorkExperience("1998-2010","xx 公司"); 68 | 69 | $resume->display(); 70 | $resume2->display(); 71 | 72 | ``` 73 | 74 | 总结: 75 | 76 | > ***原型模式***,用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 77 | 78 | > 原型模式其实就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。 79 | 80 | > 一般在初始化的信息不发生变化的情况下,克隆是最好的办法。既隐藏了对象创建的细节,又对性能是大大的提高。 81 | 82 | 83 | 上一章:[第八章 雷锋依然在人间 --- 工厂方法模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter8.md) 84 | 85 | 下一章:[第十章 考题抄错会做也白搭 --- 模版方法模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter10.md) -------------------------------------------------------------------------------- /files/chpter24.md: -------------------------------------------------------------------------------- 1 | ### 第二十四章 加薪非要老总批 --- 职责链模式 2 | 3 | 总结: 4 | 5 | 6 | 上一章:[第二十三章 烤羊肉串引来的思考 --- 命令模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter23.md) 7 | 8 | 下一章:[第二十五章 ](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter25.md) -------------------------------------------------------------------------------- /images/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/images/.DS_Store -------------------------------------------------------------------------------- /images/decorator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/images/decorator.png -------------------------------------------------------------------------------- /images/sponsor.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hulin32/design-patterns-by-php/5bac48952e666bf56714bd70ed9cbdbd6fd702ab/images/sponsor.jpeg -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [《大话设计模式》](https://book.douban.com/subject/2334288/)php版本 2 | 用自己现在用的语言重新写一遍,文中的代码均可以在终端内执行 3 | 4 | 网页版本: https://design-patterns-by-php.hulin.ink 5 | 6 | 相关资源: 7 | 8 | [Design Patterns for Humans](https://github.com/kamranahmedse/design-patterns-for-humans) 9 | 10 | [DesignPatternsPHP](https://github.com/domnikl/DesignPatternsPHP) 11 | ## 目录 12 | 13 | - [第一章 代码无错就是优 ---简单工厂模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter1.md) 14 | 15 | - [第二章 商场促销 --- 策略模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter2.md) 16 | 17 | - [第三章 拍摄UFO --- 单一职责原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter3.md) 18 | 19 | - [第四章 研求职两不误 --- 开放-封闭原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter4.md) 20 | 21 | - [第五章 会修电脑不会修收音机? --- 依赖倒转原则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter5.md) 22 | 23 | - [第六章 穿什么有这么重要吗 --- 装饰模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter6.md) 24 | 25 | - [第七章 为别人做嫁衣 --- 代理模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter7.md) 26 | 27 | - [第八章 雷锋依然在人间 --- 工厂方法模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter8.md) 28 | 29 | - [第九章 简历复印 --- 原型模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter9.md) 30 | 31 | - [第十章 考题抄错会做也白搭 --- 模版方法模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter10.md) 32 | 33 | - [第十一章 无熟人难办事 --- 迪米特法则](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter11.md) 34 | 35 | - [第十二章 牛市股票还会亏钱 --- 外观模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter12.md) 36 | 37 | - [第十三章 好菜每回味不同 --- 建造者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter13.md) 38 | 39 | - [第十四章 老板回来,我不知道 --- 观察者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter14.md) 40 | 41 | - [第十五章 就不能不换DB吗? --- 抽象工厂模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter15.md) 42 | 43 | - [第十六章 无尽加班何时休 --- 状态模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter16.md) 44 | 45 | - [第十七章 在NBA我需要翻译 --- 适配器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter17.md) 46 | 47 | - [第十八章 如果再回到从前 --- 备忘录模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter18.md) 48 | 49 | - [第十九章 分公司 = 一部分 --- 组合模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter19.md) 50 | 51 | - [第二十章 想走?可以!先买票 --- 迭代器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter20.md) 52 | 53 | - [第二十一章 有些类也需要计划生育 --- 单例模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter21.md) 54 | 55 | - [第二十二章 手机软件何时统一 --- 桥接模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter22.md) 56 | 57 | - [第二十三章 烤羊肉串引来的思考 --- 命令模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter23.md) 58 | 59 | - [第二十四章 加薪非要老总批 --- 职责链模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter24.md) 60 | 61 | - [第二十五章 世界需要和平 --- 中介者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter25.md) 62 | 63 | - [第二十六章 项目多也别傻做 --- 享元模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter26.md) 64 | 65 | - [第二十七章 其实你不懂老板的心 --- 解释器模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter27.md) 66 | 67 | - [第二十八章 男人和女人 --- 访问者模式](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter28.md) 68 | 69 | - [第二十九章 OOTV杯超级模式大赛 --- 模式总结](https://github.com/flyingalex/design-patterns-by-php/blob/master/files/chapter29.md) 70 | 71 | 72 | ## License 73 | 74 | The MIT License. 75 | --------------------------------------------------------------------------------