学习到一些PHP框架的时候,我们会接触到一些设计模式,下面我们就简单讲解一下设计模式改如何实现。
常用的设计模式我们分为三大类:创建性模式、结构性模式、行为性模式。创建性模式包括:单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、对象池模式、原型模式;结构性模式:适配器模式、桥接模式、组合模式、装饰器模式、依赖注入、门面模式、链式操作、代理模式、注册器模式(容器);行为性模式:观察者模式、责任链模式、模板方法、策略模式、访问者模式、空对象模式、遍历模式、状态模式、命令模式;下面我们对这24个模式一一做讲解。
单例模式
直接上代码


简单工厂模式


看了这个简单工厂,大家可能没什么印象,下面我们用一个实例来描述它的作用,点击查看实例。
工厂方法模式
工厂方法跟简单工厂其实区别不是很大,简单工厂创建操作类的时候还是需要进行判断我们要实例化那个类,而工厂方法则把这个判断交给工厂基类的子类,也就是说工厂方法模式需要我们定义一个抽象工厂基类。前面那个简单工厂实例里面,我们定义了四则运算的抽象基类,如果使用工厂方法,我们还需要定义工厂的抽象基类。因为比较容易理解,我们就不用代码实现了。
抽象工厂模式
抽象工厂和工厂方法基本上也是一样的,大家直接看抽象工厂的规则就明白了。
1、每个子工厂必须继承同一个抽象基类或者实现同一个接口。
2、每个子工厂必须包含多个方法。
3、每个子工厂的方法必须一样。
对象池模式
对象池模式跟我们下面说的注册器模式(容器)实现方式基本是一样的,它们不同的是关注点不一样,对象池关注的是性能,也就是对于一些浪费资源的对象的创建,我们用单例模式实现,容器则关注的是获取这个对象方便,管理方便等等,我们用代码来实现一下对象池模式。

原型模式
原型模式关注的是对象的复制问题,我们都知道变量的赋值是正常的赋值,就是只是把值赋值过去了,对象的赋值就是引用,如果说一个对象中的一个属性是一个对象,那么我们克隆的时候这个属性也是引用,这就是我们说的浅复制,实际应用中我们需要这个属性是一个新的对象,也就是我们需要深复制,听起来有点绕,我们用代码来说明一下。
浅复制

深复制

原型模式实现浅复制

当然浅复制在实际应用中基本用不到。
原型模式实现深复制

通过上面的例子,我们就能够知道原型模式其实就是不clone,而是定义一个原型,在原型子类中实现方法进行复制,具体这个复制能力是浅复制还是深复制,看自己的用途了。
适配器模式
为了方便大家理解适配器模式,我们用例子是实现,比如我们是电脑生产厂家,定义一个抽象基类,其中有电脑开机和关机的方法。生成某一型号电脑也就是抽象类的子类,代码如下:

为了扩大业务,我们与梦中遥控公司合作,他们的遥控器可以控制各种型号电脑的开关机,一般的逻辑是我们在抽象基类中定义遥控开关机的方法,然后在各种型号电脑实现遥控开关机方法,代码如下:


我们生成几百台各种型号电脑,需要在子类一次又一次的重复添加这俩个方法,当然这还在我们接受范围之内,只是觉得有点蠢而已。
现在业务进一步扩大,我们又合作了赏金遥控公司,他们公司是通过SJTurn($type)来实现遥控开关机,type是1就开机,type是0就关机,这下事情就麻烦了,我们需要对抽象基类和他的所有子类添加这个方法,这种工作搁谁都不会再淡定了,好吧,就算你还淡定,万一哪天我们又合作很多遥控公司,你还会淡定吗?好,算你厉害,你还淡定,但是随着合作公司越来越多,Computer越来越大,就算你还淡定,程序就淡定不了了,崩溃了,那我们就考虑一下为什么会出现这种事情呢?像前面那种我们有了合作公司就给抽象基类添加方法,代码实现违反了代码的开闭原则,我们的基本要求是对扩展功能进行开放,对修改进行关闭,也就是说新的接口功能可以添加,旧的抽象类Computer不能修改,那么总有方法解决吧,这就是我们接下来要说的适配器模式。给每一个合作公司定义一个抽象基类或者接口,为了方便区分我们自己的抽象基类,我们就定义接口了,然后做适配器,代码如下:


看到这里大家是不是对适配器模式有一个清晰直观的认识了呢?
桥接模式
桥接模式就是把类的实现抽离出来,概念比较抽象,我们用一个例子来说明,比如我们要写字,这个字我们要求有1号红色、1号蓝色、1号绿色、2号红色、2号蓝色、2号绿色、3号红色、3号蓝色、3号绿色,共计9种字体,一般情况下我们需要准备这9种笔,也就是9个笔类才能完成这个工作,现在我们把字体大小和字体颜色抽离出来,分成1号笔、2号笔、3号笔3个笔类,红色颜料、蓝色颜料、绿色颜料3个颜料类,共计6个类就可以完成上述工作,如果说需要的字体更多,那么不抽离的笔类就更多了,我们就不实现不抽离的代码了,直接实现抽离的桥接模式,如下:


桥接模式相对来说还是比较容易理解的,其实就是一个对象可以调用另外一个对象的属性和方法。解耦以及减少代码量。
组合模式
组合模式根据名字我们就可以猜到它的作用是什么,把几个模块组合成一个模块,比如一个表单有用户名输入框,密码输入框等等,我们把用户名输入框当成一个对象,把密码当成一个对象,把它们组合起来生成一个表单,如果需要其它输入框继续组合即可,表单这个组合有点过于简单了,我们讲一个逻辑稍微复杂点的,比如我们有很多公司,公司有人力资源部门,公司又分为北京总公司,天津分公司,天津下属公司,我们用代码来实现这个结构,并封装一个公司结构输出,代码如下:




逻辑可能有点绕,大家多看几遍,多写几遍代码就可以理解,就是组合而已。
装饰器模式
未完待续。。。