简单说说对编程中设计模式的理解

简单说说对编程中设计模式的理解

设计模式主要是针对面向对象的思考方法,即将万物都抽象成类来描述,然后基于类生成具体的对象。

这个类其实就是一个模板,所以最基础的设计模式便是模板模式,模板模式非常简单,即定义一个基类,然后给出来一些虚拟或抽象方法,具体的实现在子类中完成,这是面向对象编程里最基础也最简单的用法。

如一篇文章,它有标题,有内容,那么这个就可以成为一个模板,标题作为一个方法,内容作为一个方法,这样子类中返回的字符不同,便能够成为不同的类型文章,如在标题字符串描述里,可以是有有图像与无图像的。

模板方法强调在对基类的调用上拥有统一的接口,这样才能够实现足够的延展性,它强调的是模板式。

而更进一步,如果仅仅接口方法只是很少量时,可以视作为策略模式,比如定义一个方法名称,是两个整型参数,在方法内部可以实现加法,也可以实现减法,也可以实现乘法等各种处理,在外部看来选择不同的继承类,就能够实现不同的功能,所以这就成为了策略模式。

策略模式与模板模式的最大区别在于,策略模式关注的是实现选择,而这个在策略模式中,通常是引入一个Context 的上下文类,策略本身的基类是策略模板,而选择什么策略,则由Context 来负责调用。

为什么要有一个Context,比如出现多个策略需要连续判断时,Context调用一个策略类的方法后,还可以记录下该策略的结果,然后带着上个的结果传入到下一个策略方法中,然后再进行计算。

换句话说,引入Context上下文类创建的对象,目的就是为了记录并传递策略的结果,所以它可以是上下文相关的。

一种常见场景就是用Context记录当前运算状态或步骤,比如处理一张图片,先进行了灰度处理,然后再进行提轮廓,因为有了上下文的对象,系统随时可以知晓当前的状况,无论对于异步处理还是多线程编程都是非常有益的。

对于能直接新建的对象,只需要直接创建就好了,但是总是事不如人意的,有时候对于产生的对象是需要统一管理的,尤其是复杂的对象,同时并不需要上下文有那么密切的相关性。

比如说生产一辆轿车后,再生产一辆卡车,这是基于不同需求的选择,但是生产轿车与生产卡车之间并无上下文联系的需求,它们甚至是可以进行同步进行的。

这种情况下,无疑可以考虑使用工厂模式,在同一个工厂出厂的对象无疑都可以打上相应标志,并且事后无论是要统一销毁还是怎么处理,都会非常方便。

工厂模式中只关心产生对象,所提供的方法接口,对于产生的顺序或是之间需要什么组合要求,并不关心。

简单的工厂对于一些简单场景是很有用的,比如说,一个日志记录,是记录到硬盘还是记录到内存还是记录在哪里,可以用工厂产生记录对象来后期决定。

但是打开工厂方法,对于一辆车的内部流程,涉及到了具体的组装时,就需要采用不同的方法进行构建。

这种构建的流程大多是可以复用的,比如给封闭轿车安轮子与给敞篷型轿车安轮子,并没有不同的地方。

但是一辆车安车顶与安轮子显然是两个不同的活,这个无法直接通过策略模式完成,因为策略模型可以关心完成安什么样的轮子,安轮子的步骤,却在概念上不能组装车子。

所以在这里又有了构建者模式,构建者模式中,复杂的构建与其表示相分离,它类似于策略模式,但是来源的构造并不基于同一个策略类。

一系列策略可以构成同一类零件,而不同零件可以构成不同的部件,而不同部件则可以构建出一个成品。

这就是它们的区别,在构建者模式中,包含了零件与部件,比如说一辆车可以安个圆顶,也可以安个方顶,那么这可以用构建者模式来实现圆顶构建者或方顶构建者。

构建者模式的最大特点是:它是可以在现有对象上,将不同部件组成一个新对象。

如一个汉堡,用纸装或用盒子装,而装的汉堡可能用奥尔良鸡腿,也可能是用油炸鸡腿所构成,而到底是用纸或盒还是用什么鸡腿,这之间并无任何关系,这就比较适合用构建者模式。

对象之间的关系并不是完美而简单的,有时候会出现相互对象的依赖,这会非常麻烦,最有效的方法是除了统一调度外,还必须考虑有意外的情况,从而能够进行临时调度。

比如高铁的各个列车,它们的先后次序很重要,需要并行不紊的进行,如果依赖于高铁列车之间相互通讯必然会引起混乱,因为消息的传播效率很低。

所以这就需要一个广播机制,一个中介的对象来与其它对象之间进行交互,这就好比一个数据中心,而其它对象只是各个终端,所有的终端都只与数据中心进行通讯。

这种情况所设立的中心,被称为中介者,将数据广泛发给所有的其它相应对象可以看到,这就类似于一个频道,然后所有的对象信息都在这上面进行交互。

这种星型结构,也是现代网络最常见的结构,就目前来说它是一个相对较好的方案。

对于终端的接入,有时候需要判断的它的状态,例如是否已经接入,或是已经断开,以确定数据可以发送,这种情况称为事件。

它并不局限于这个场景使用,但以这个场景为例,这种基于事件的模型已经在一些语言里被实现得很好,即事件模型,通过调用某一个事件来实现状态通知。

因为事件是离散的,所以必须要用离散的方法进行处理,这可以使用轮循或是方法调用来实现,事件的订阅与取消,这就是发布者订阅者模式,同样也可以是称为拜访者模式。

这种模式的好处是,对于接入的终端可以开放权限,透露一些对象内部的细节,比如一个类中的成员变量值是非公开的,但数据中心可以通过事件方法将这个值告诉接入者,一方面保持了外面接口的统一,另一方面可以针对特殊需要,给外来接入的对象公开一些私有的值。

比如一个窗口上的按钮,它的点击事件发生时,要传出内部的某个值,这个是被允许的,同样甚至可以允许传出一个核心的对象让外部进行改变,这显然是违反封装性原则的,不过允许哪些可以对外传出,实际上还是由类的设计来控制的。

如果A事件引起B事件,而B事件满足某条件引起C事件,这种就可以称为责任链模式,一种典型场景比如选择省市地区街道时,它会进行一层层的过滤,事实上便构成了一个事件链。

责任链模式显而易现的是,某个对象的状态改变基于某一个对象改变的通知,这样会带来很多好处。

比如说当一个省被选择后,那么省被选择定了,就要筛选出在B中显示哪些列表,但假如A是一个类,B是一个类,A如果去直接控制B的类的成员,会引起很麻烦,设计起来考虑东西很多,因为A究竟应该能够直接控制多少B的成员才能满足设计需要,在复杂场景下很难说。

所以不如只由A通知B,这里选中了某个值,然后交给B,B根据这个值自己决定应该呈现什么数据,这样灵活性与扩展性就大大增强了,同时关于B的内部成员的职责与作用也被控制在了B之内。

如果是在多人协作编程项目时,A类的编写者只需要编写A类,B类只需要负责自己的B类就可以了,这样职责会非常明确,管理起来会非常方便。

对象在传递的时候,有时候原本的对象是不够中的,需要附加上一些信息,在一些动态语言里这个事情比较简单,直接扩展属性就行了,但是这样有时候会引起一些纷争,因为原始对象被修改了,并且这种修改通常不可逆,新增的动态属性并不能删除掉。

所以干脆不如另外做一个新类,将它进行包装,而这个原来的对象成为新类的成员之一,这样就构成了装饰器模式。

装饰器模式有个最大的好处时,可以随时丢掉新创建的对象,然后仍然使用原来的对象,所以显得非常灵活。

 

三符风云涌

发表评论