阅读 241

模板方法模式 及 设计模式总结

模板方法模式 及 设计模式总结

定义

模板方法模式是基于继承的代码复用技术。

通过继承,让父类成为子类的模板,所有重复的代码都应该上升到父类去,而不是让每个子类都去重复。

使用场景

当我们要完成在某一细节层次一致的一个过程或一系列步骤,但其个别步骤在更详细的层次上的实现可能不同时,通常考虑使用模板方法模式来处理。

模板方法模式是很常用的设计模式,在类的继承中往往会用到这个模式。

Sample

mosby Model-View-Presenter library

乍一看可能有些复杂,实际上只有一个方法 createPresenter() 将创建对应的 Presenter 的任务交给子类去处理。提高了父类 MvpActivity 的复用性。而将所有子类中共同的逻辑:管理 Presenter 和 View 之间的联系,提到父类中处理。增加了代码的可维护性。

优点

  1. 封装不可变的部分,扩展可变的部分
  2. 将公共代码提取到基类中,便于维护

缺点

每一个不同的实现都需要一个子类来实现。

注意事项

Java 中的模板方法,为了防止基类中定义的方法实现被意外修改,一般会将在基类中实现的方法设置为 final .

你将在真实世界代码中看到模板方法模式的许多变体,不要期待它们全都是一眼就可以被认出的。

对比

策略模式和模板方法模式都封装算法,一个用组合,一个用继承。

策略模式定义一个算法家族,并让这些算法可以互换,每个算法都被封装起来,所以客户可以轻易使用不同算法。

模板方法模式定义一个算法大纲,由子类决定其中某些步骤的内容,这样一来算法中的个别步骤可以有不同的实现细节,但是算法的结构依然维持不变。

好莱坞原则

别调用(打电话给)我们,我们会调用(打电话给)你。

高层组件对待低层组件的方式是“别调用我们,我们会调用你”。父类控制算法的大纲,只有在需要子类实现某个方法时,才调用子类。子类只是简单用来提供一些实现细节。

并不是说低层组件完全不能调用高层组件中的方法,我们要做的是避免让高层和低层组件之间有明显的环状依赖。

总结

创建型模式

抽象工厂:提供一个创建一系列或相关依赖对象的接口,而无需指定它们具体的类。

建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

工厂方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类。

原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

单例模式:保证一个类只有一个实例,并且提供一个访问它的全局访问点。

创建型模式隐藏了这些类的实例是如何被创建和放在一起,整个系统关于这些对象所知道的是由这些抽象类所定义的接口。创建型模式在创建了什么,谁创建它,它是怎么被创建的,以及何时创建这些方面提供了很大的灵活性。

通常设计模式从工厂方法开始,当设计者发现需要更大的灵活性时,设计便会向其他创建型模式演化。

结构型模式

适配器模式:将一个类的接口转换成客户希望的另外一个接口。使得原本由于接口不兼容而不能在一起工作的类可以在一起工作。

桥接模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。通过对象组合的关系,解耦不同方向的变化。

组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。

装饰器模式:动态地给一个对象添加一些额外的职责。

外观模式:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

享元模式:运用共享技术有效的支持大量细粒度的对象。

代理模式:为其他对象提供一个代理以控制对这个对象的访问。

行为型模式

观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知并被自动更新。

模板方法模式:定义一个操作的算法骨架,将一些步骤延迟到子类中,使得子类在不改变一个算法的结构即可重定义该算法的某些特定步骤。

命令模式:将一个请求封装为一个对象,从而可以使用不同的请求对客户进行参数化,可以对请求排队或请求记录日志,以及支持可撤销的操作。

状态模式:允许一个对象在其内部状态改变时改变它的行为,让对象看起来似乎修改了它的类。

责任链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

中介者模式:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

访问者模式:表示一个作用于某对象结构中的各元素的操作。使得可以在不改变各元素类的前提下定义作用于这些元素的新操作。

策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

备忘录模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。

迭代器模式:提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。

几个原则

单一职责(SRP):就一个类而言,应该仅有一个引起它变化的原因。

开放-封闭原则:软件实体(类,模块,函数等等)应该可以扩展,但不可以修改。

依赖倒转原则:高层模块不应该依赖低层模块。两个都应该依赖抽象。抽象不应该依赖细节。细节应该依赖抽象。

里氏代换原则(LSP):子类型必须能够替换掉它们的父类型。(在软件里面,把父类都替换成它的子类,程序的行为没有变化。只有当子类可以替换掉父类,软件单位的功能不受到影响时,父类才能被真正复用,而子类也能够在父类的基础上增加新的行为。)

迪米特法则(LoD):也叫最少知识原则。如果两个类不必彼此直接通信,那么这两个类就不应该发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。(根本思想是强调了类之间的松耦合。在类的结构设计上,每一个类都尽量降低成员的访问权限,不需要让别的类知道的字段或行为就不要公开。)

使用建议

为实际需要的扩展使用设计模式。不要只是为了假想的需要而使用设计模式。

简单才是王道。如果不用设计模式也能设计出更简单的方案,那就去干吧。

模式是工具而不是规则,需要被适当地调整以符合你的需求。

Refs

《JAVA与模式》之模板方法模式

模板模式

《大话设计模式》

《Head First 设计模式》


by Eric