纸上谈兵设计模式


工厂模式:给我一个对象实例。同一个工厂用于生产一类产品,这类产品有相同的接口基类。特殊情况下一个工厂可能生产一系列相关的产品。用于解决产品生产过程多样化的情形。

工厂方法模式:为创建不同的实例预先生成不同的工厂(一般继承于工厂抽象类)。创建实例,用多态性逻辑替代可枚举的条件逻辑。

单件模式:仅需要一个实例,如工厂。实例化方法返回静态成员,或嵌入类的静态成员,或线程安全(双检锁)的静态成员引用。必须提供一个全局访问点。

抽象工厂模式:同一系列多个产品用同一个工厂创建,需且仅需一座工厂,不同系列的同一种产品通常继承于该产品抽象类。动态创建N座工厂用来生产N个系列的产品,所以这些工厂本身也可以视作一系列的产品,可引入一个工厂抽象类,同时定义一个这些工厂的工厂(即工厂蓝图),参数传入系列代码,即可返回系列产品。用来解决产品系列多样化的情形。

生成器模式:生产一个复杂的产品。先用工厂Director创建生成器Builder和原料,再指导Builder创建(组装)产品。用于处理生产过程比较复杂的情形。Builder可能继承于IBuilder。

原型模式:实现该类的.Clone()。new原型实例,用clone()返回新实例。深拷贝需要序列化机制。也可以引入一个原型管理类。

适配器模式:若需要把各种不同的服务转换为标准接口,可以派生类实现适配器接口或组合原服务实现适配器来实现一致的标准接口。用类适配构建的类无法适应适配器子类,用对象适配器构建类时可能需要服务公开更多的方法。

桥接模式:多维度扩展会引起子类多重继承,数量倍数增多时,考虑组合方式引用其中一些基类,重构为成员对象。一个构件有多于一个的抽象化角色和实现化角色,系统需要它们之间进行动态耦合。类似装饰模式原理,引入bridge类,注入抽象对象,并重新实现抽象类方法,而不是通过子类型化重写方法。只要继承bridge类,就可以更好地实现另一维度功能的扩展。

装饰模式:装饰方法调用时,运用多形性原理(方法动态调用或事件多次绑定),执行所在类的装饰方法。

装饰模式特例:引入包装类,组合并继承原服务,引用该成员对象(原服务),重写方法,根据多态性,这些方法可以动态调用实际的对象方法。

特例:多态方法调用返回装饰类,实现代码连续编码。

派生包装类,扩展新功能并base.Method(),允许传入被装饰对象,对其进一步包装,调用新功能时可以通过多次包装而叠用。base.Method()调用的是包装基类的方法,如果没有包装类多态调用,最终是静态调用基类的方法。而通过包装类的方法多态调用,最终调用了传入的被装饰对象的方法,该方法被调用后,再递归调用传入的被装饰对象的方法。

创建新包装对象时需要传入被装饰对象实例,经过包装类处理运用多态性原理实现了引发所有被装饰对象的方法调用。

功能的扩展是通过包装类的多个派生类实现的,而不是多重继承,巧妙地应用了IS-A原则和基类的多态性,多次包装(组合调用)可以动态选择需要的新功能,有效减少了子类数量。

之所以能减少类数量,是因为能被多次包装。之所以能被包装,是因为各种服务都继承于同一个基类。之所以被装饰对象方法能被调用,是因为重新包装了该方法。之所以要重新包装,是因为不用多态性,只能调用基类的方法,而不能调用传入被装饰对象的方法,而运用多态调用可以实现被装饰对象的调用。

相当于实现了:不是通过静态的继承结构实现功能扩展,而是通过运行期创建对象时通过传入基类对象作为参数实现功能扩展。实际上是传入了被装饰对象的实例,用多态性,调用了该对象的方法。

组合模式:针对于整体由各部分对象组合而成,又同属一个基类的情形。整体内部置入容器,统一处理局部对象,对外保留一致行为。

外观模式:封装复杂的子系统,提供一致,简洁的用户接口。
享元模式:提供一个容器缓存可枚举的细粒度对象实例,创建新实例可以引用这些原型对象(共用部分)。共享元素通常由享元工厂预先创建。
代理模式:引入中间类,模拟调用实际类,有时会继承于同一个接口。
模板模式:派生类override基类的某些方法,这些方法被基类的模板方法作为子程序调用。基类实现一个算法的不变的部分,并将可变的行为留给子类来实现。wpf,aps.net框架中的事件编程模型,是观察者模式和模板模式的综合运用。

命令模式:将方法调用(产生消息,引发事件),封装为命令(消息)对象,可以实现命令的发送,传达和执行。将行为抽象为对象。Undo操作,维护一个Command列表,执行Command.Undo(),而不是维护一个UndoCommand列表。

迭代器模式:维护一个内置的当前位置指示器变量,用于遍历集合中的元素。

观察者模式:被观察对象(主题对象)持有所有通知对象(观察者)的引用的列表。处理一对多的数据结构中实现消息分发。等同于声明一个事件。

推模式是当有消息时,把消息信息以参数的形式传递(推)给所有观察者,观察者不能“按需所取”;而拉模式是当有消息时,通知消息的方法本身并不带任何的参数,是由观察者自己到主体对象那儿取回(拉)消息。主要区别在于直接响应消息的对象是数据持有对象(推)还是数据分析对象(拉)。

职责链模式派生节点类,重写消息处理函数(如果从IChain接口继承还需重写消息接收,转发函数),并串联成消息链,起始节点响应/处理消息(命令/事件/方法),并递归(传递)该消息及其参数到下一个节点处理,按序处理指定消息,直至最终节点。在节点创建后完成消息链的组装工作。

解释器模式:用于分析文法。
分析类SQL语法:将单词压入堆栈,根据上下文,单词逐个出栈由职责链分析,分别归约为参数列表或动词。分析结果的动词分别由相应的命令执行。

中介模式:客户对象引发的消息汇集到一个中介类统一处理,中介类分别持有所有客户对象的引用,并通知(协调)相应的客户对象。
特例:MVC模式,界面元素引发事件,消息由Controller统一处理,更新Model,并更新相关的界面元素或导航View。通常Controller持有States集合和Navigator导航器,而Navigator会有ViewManager,引用View集合。

备忘录模式:在环境改变之前将当前环境状态(对象及其状态)保存在备忘录列表中,用于将来还原现场。

状态模式:状态管理类维护一组状态派生类(继承于状态接口)对象和当前状态,所有可能状态下可能的方法都在状态接口基类中声明,并在派生类中实现。改变状态时,因为很多方法在不同的状态下有各不同的处理方式,对当前状态判断逻辑转换为多态性响应事件逻辑。这些状态相当于Context。

策略模式:从一组预定义的策略中选择(创建策略实例)并应用(注入)某个策略来实现指定功能。通常需要一个策略权衡(选择)类,策略工厂或策略选定者。

黑板模式:将对象预置于可访问的容器(如Hash表)中,并关联一个唯一关键代码,作为存取入口。

访问者模式:实现IAccept的对象(被访问对象)具有Accept(Visitor)方法,该方法回调Visitor.visit(this),根据方法签名(参数类型)自动调用合适的重载的Visitor.visit()方法,依据Accept对象的所属类别分别处理。对类型的判断逻辑转化为overload的函数参数类型(实参静态类型静态绑定到相同类型或其基类的形参)自适应逻辑。通常需要遍历被访问对象集合时应用到访问者模式统计数据,定义一个访问类相当于定义一个统计方式。

===================小结=======================

创建模式:
目的:需要消费产品。
过程:创建产品。
[产品(类型,系列,数量)复杂化的问题。]
创建多个同类产品。== new创建。或者定义clone()方法,预先创建产品原型,通过复制创建新产品。
创建N种相同基类对象。 == 产品泛化,new创建。或者引入工厂,实时生产。或者Activator反射创建。
创建M个一系列(同一系列,不同基类)对象。  == 须引入一个工厂,有M个生产车间(方法)。
创建N种*M个系列的对象(M个系列的产品各N种) == 工厂泛化,引入N种工厂。产品泛化,由工厂生

产。N个工厂相当于N种产品,所以也可引入抽象工厂,创建这些工厂。
仅需创建1个产品:单件模式。
[创建过程复杂化的问题。]
建造产品,或委托给指导者来建造产品。若建造过程多样化,需引入建造者接口基类。

结构模式:
目的:对象间建立联系。
过程:得到对象的引用。
[接口复杂化问题]
适配器模式:定义一个接口,并让其中一类对象提供标准的接口。
组合模式:让所有对象提供可递归组装的标准接口,结构也具有相同接口,可递归组装。
外观模式:结构外观提供简洁的接口。
[对象个数复杂化问题]
享元模式:维护并共享对象间公共元素部分。
[依赖关系复杂化问题]
依赖注入:通过在容器里,设值,构造子或接口等自动注入方式构建对象.

解构对象:
目的:解构并认知对象。
过程:得到对象的信息。
迭代器模式:枚举集合中元素对象引用,逐个处理。
解释器模式:分析文法。
黑板模式:用散列码标识对象,关联对象引用。
MVC模式:由控制器维护界面和数据状态。

功能增强:
目的:增强对象的功能。
过程:定义新功能,并外接到现有对象上。
桥接模式:选用一个扩展的功能对象。
装饰模式:增强现有功能,选用一个或多个扩展功能。
模板模式:通过继承扩展功能。
访问者模式:扩展新的(集合处理)方法,而不必改动现有的集合元素类。
代理模式:保留相似接口,增强原有类的功能。
AOP:通用功能(横切方面功能)以拦截器方式,注入代理类,原有功能由拦截器回调。
控制反转:由继承类实现具体策略,行为,算法.

行为模式:
目的:对象互动,相互通信。
过程:引用对象,发送消息,调用方法。
[消息分发过程或目的地复杂化]
代理模式:透明处理获取原始服务的对象引用过程或调用过程。
职责链模式:按先后顺序,按职责处理消息,并递归发送消息。
观查者模式:观查者向被观查者预先订阅消息,以便分发。
策略模式:在所有解决方案中选取其中一个策略。
状态模式:在对象不同状态时,分选不同的处理方式。
绑定模式:绑定对象观察绑定源的改变,并通知绑定目标,消息简单但数量多。
推模式:设置(推送)数据到数据处理对象,并通知其处理。
拉模式:通知数据处理对象,更新要处理的数据,并处理。
MVC模式:Controller观察View(s),Controller更新View(s)和Model,使其同步;Model改变通知View(s)拉数据更新;
MVP模式:Presenter观察View和Model,并保持View和Model同步更新。
[消息类型复杂化]
命令模式:维护消息类型,包括可撤消的消息,可更改的消息,可重定向的消息等。
中介模式:不同消息来源,消息类型统一处理,转发。

=====================================编程原则===============

Open-Closed Principle原则讲的是:一个软件实体应当对扩展开放,对修改关闭。即:封闭对原来代码的修改,开放对原来代码的扩展(如类的继承,接口的实现),找到系统公共的部分(代码或逻辑),抽象化并封装起来;而将可变的因素,定义为接口。抽象化与实现化的简单实现,也就是“开-闭”原则。
依赖倒置(Dependence Inversion Principle)原则讲的是:要依赖于抽象,不要依赖于具体。
接口隔离原则(Interface Segregation Principle)讲的是:使用多个专门的接口比使用单一的总接口总要好。换而言之,从一个客户类的角度来讲:一个类对另外一个类的依赖性应当是建立在最小接口上的。
迪米特法则(Law of Demeter或简写LoD)又叫最少知识原则(Least Knowledge Principle或简写为LKP),也就是说,一个对象应当对其它对象有尽可能少的了解。类的单一职责原则,重写这个类仅有一个原因。一个类的功能要单一,只做与它相关的事情。
合成/聚合复用原则(Composite/Aggregate Reuse Principle或CARP)经常又叫做合成复用原则(Composite Reuse Principle或CRP),即优先使用对象组合而非继承。
通过参数传递类,对象,方法可以降低耦合性.
服务的配置应该与使用分开。
尽量重用代码和流程(行为)逻辑。
设计模式的目的就是降低对象间的耦合性,提高对象的复用性。
在面向对象程序里,我们在一个地方用条件逻辑来决定具体实例化哪一个类,以后的条件分支都由多态来实现,而不是继续重复前面的条件逻辑。习惯上会进一步把创建对象的逻辑部分封装在一个工厂类里。
面象对象编程,重要的任务是在合理的时机创建合理的对象。
继承机制组合接口用来实现新的功能(类结构型模式);或者通过组合一些对象,从而实现新的功能(对象结构型模式)。
继承是两个类之间高耦合的静态关系,如果不需要引用抽象类,则不需要继承。
学习代码方法,先看运行效果,再断点跟踪,最后分析类图。

=======================编程就是抽象过程============================

引用李建忠老师的总结,摘录于此. http://jzli.techjie.com/?p=7

基本的编程抽象
* 忘掉数据(无论对象/指针/引用)在内存中的地址,将精力集中在数据所表达的类型实例概念上

面向过程编程的抽象
* 忘掉函数调用的压栈/出栈细节,将精力集中在函数之间的调用关系上

基于对象编程的抽象
* 忘掉对象中数据成员(字段)的内存布局,将精力集中在数据成员对对象状态的表达上
* 忘掉对象中函数成员(方法)的绑定机制以及this指针,将精力集中在函数成员对对象行为的表达上

面向对象编程的抽象
* 忘掉类继承下子类对象中数据成员的内存布局,将精力集中在继承所带来的子类化的概念上
*忘掉虚函数相关的虚表vTable结构,将精力集中在虚函数所带来的动态多态的概念上

泛型编程的抽象
* 忘掉模板的各种编译与绑定机制,将精力集中在用一组抽象的概念来表达一组类型的需求条件上

面向组件编程的抽象
* 忘掉组件平台背后的元数据等机制,将精力集中在组件化模块所表达的黑盒概念上

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值