`

四十六:模式方法模式

阅读更多
模式方法模式是类的行为模式,准备一个抽象类,将部分逻辑以具体方法以及具体构造子的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方法实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式的用意.它是基于继承的代码复用的基本技术。在定义新的子类的时候,应当考虑哪些操作是必须置换掉的,哪些操作是可以置换掉的,以及哪些操作是不可以置换掉的,使用模板方法模式可以使这些责任变得清晰.

一:模板方法模式中的角色
这里涉及到两个角色
(A)抽象模板(Abstract Template)角色,它有如下责任:
(a)定义一个或多个抽象操作,以便让子类实现,这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
(b)定义并实现一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现.
(B)具体模板(Concrete Template)角色有如下责任:
实现模板方法
这个模式应用在BaseEntity的设计中.......

二:一个例子
考虑一个计算存款利息的例子。假设系统需要支持两种存款帐号:货币市场(MoneyMarket)帐号和定期存款(CD)帐号。这两种帐号的存款利息是不同的,因此在计算一个存户的存款利息时,必须区分两种不同的帐号类型
这个系统总行为应当是计算出利息,这也就决定了作为一个模板方法模式的顶级逻辑应当是利息计算。由于利息计算涉及到两个步骤:一是确定帐户类型,二是确定利息的百分比,因此系统需要两个基本方法:一个给出帐号类型,二是确定利息的百分比,因此系统需要两个基本方法:一个基本方法给出帐号种类,另一个方法给出利息百分比,这两个方法构成具体逻辑,因为帐号类型不同,所以具体逻辑会有所不同.显然系统需要一个抽象角色给出顶级行为的实现,而将两个作为细节步骤的基本方法留给具体子类实现.
package cai.milenfan.basic.test; 
/*这个抽象角色给出了顶级逻辑的骨架,即calculateInterest()的内容,只是将内容的具体步骤委派给不同的基本方法, 
  *在这里分别是doCalculateAccountType()和doCalculateInterestRate(),而这两个抽象方法则留给具体子类实现
  */ 
/*final*/ public abstract class Account {//final类没有子类
protected String accountNumber; 
   public Account() 
   { 
accountNumber = null; 
   } 
   public Account(String accountNumber) 
   { 
       this.accountNumber = accountNumber; 
   } 
   //模板方法,计算利息数额
   final public double calculateInterest()//final方法不能被重写
   { 
       double interestRate = doCalculateInterestRate(); 
       String accountType = doCalculateAccountType(); 
       double amount = calculateAmount(accountType, accountNumber); 
       return amount * interestRate; 
   } 
   //模板方法,留给子类实现
   abstract protected String doCalculateAccountType() ; 
   //模板方法,留给子类实现
   abstract protected double doCalculateInterestRate() ; 
   //基本方法,已经实现
   final public double calculateAmount(String accountType, String accountNumber) 
   { 
       //retrieve amount from database...here is only a mock-up 
       return 7243.00D; 
   } 
} 


package cai.milenfan.basic.test; 

public class MoneyMarketAccount extends Account{ 
public String doCalculateAccountType() 
   { 
       return "Money Market"; 
   } 
   public double doCalculateInterestRate() 
   { 
       return 0.045D; 
   } 
   //public double calculateInterest(){},final方法不能被重写,但可以被重载
} 


package cai.milenfan.basic.test; 

public class CDAccount extends Account{ 
public String doCalculateAccountType() 
    { 
        return "Certificate of Deposite"; 
    } 
    public double doCalculateInterestRate() 
    { 
        return 0.065D; 
    } 
} 


package cai.milenfan.basic.test; 

public class Client{ 
private static Account acct = null; 
   public static void main(String[] args) 
   { 
   acct = new MoneyMarketAccount(); 
       System.out.println("Interest earned from Money Market account = " acct.calculateInterest()); 
   acct = new CDAccount(); 
       System.out.println("Interest earned from CD account = " acct.calculateInterest());
   } 
} 


三:继承作为复用的工具
很多面向对象的设计专家从1986年就开始警告继承关系被滥用的可能,有一些面向对象的编程语言如SELP,甚至将类的继承从语言的功能中取消,改为完全使用委派,其他的设计师虽然不提倡彻底取消继承,但无一例外地鼓励在设计中尽可能使用委派关系代替继承关系(状态模式,策略模式,装饰模式,桥梁模式以及抽象工厂模式均是将依赖于继承的实现转换为基于对象的组合和聚合实现,这些模式的要点就是使用委派关系代替继承关系).
注意,继承不应当被滥用,并不意味着继承根本就不该使用,模板方法模式鼓励恰当地使用继承,此模式可以用来改写一些拥有相同功能的相关的类,将可复用的一般性行为代码移到基类里面,而把特殊化的行为代码移到子类里面.

四:Java语言里使用过的模板方法模式
(A)HttpServlet技术
作为Java对Web系统的解决方案,HttpServlet技术是建立在模板方法模式的基础之上的,HttpServlet类提供了一个service()方法,这个方法调用7个do方法中的一个或几个,完成对客户端调用的处理,这些do方法则要由具体HeepServlet类提供................(详见专题)
(B)javax.swing.table.AbstractTableModel
(C)javax.swing.AbstractListModel

五:重构的原则
在抽象类一节中曾经谈到,在对一个继承的等级结构做重构时,应当遵从的原则便是将行为尽量移动到结构的高端,而将状态尽量移动到结构的低端,本节将继续讨论这个问题,并将这个重构原则与模板方法模式结合起来,1995年Auser曾指出:
(1)应当根据行为而不是状态定义一个类,也就是说,一个类的实现首先是建立在行为的基础上的,而不是建立在状态上的
(2)在实现行为时,是用抽象状态而不是用具体状态,如果一个行为涉及到对象的状态时,使用间接的引用而不是直接的引用,换言之,应当使用取值的方法而不是直接引用属性.
(3)给操作划分层次。一个类的行为应当放到一个小组核心方法里面,这些方法可以很方便地在子类中加以置换
(4)将状态属性的确认推迟到子类中。不要在抽象类中过早地声明属性变量,应当将它们尽量推迟到子类中去声明。在抽象超类中,如果需要状态属性的话,可以调用抽象取值方法,而将抽象取值方法的实现放到具体子类中.
如果能够做到上面4个原则,那么就可以在等级结构中将接口与实现分隔开来,将抽象与个体分割开来,从而保证代码可以最大限度地被复用.
分享到:
评论

相关推荐

    Head First 设计模式 JAVA源码

    第二讲:工厂方法模式 第三讲:抽象工厂模式 第四讲:工厂模式在开发中的运用 第五讲:单例模式 第六讲:原型模式 第七讲:建造者模式 第八讲:装饰模式 第九讲:策略模式 第十讲:观察者模式 第十一讲:享...

    敏捷软件开发:原则、模式与实践.pdf

    第二十六章 PROXY模式和STAIRWAY TO HEAVEN模式:管理第三方API 第二十七章 案例研究:气象站 第Ⅵ部分 ETS案例研究 第二十八章 VISITOR模式 第二十九章 STATE模式 第三十章 ETS框架 附录 附录A UML表示法Ⅰ:CGI...

    Spring Cloud Reference Guide 文字版 ,英文

    知识点四十六:提供加密属性的服务(Serving Encrypted Properties) 知识点四十七:定位远程配置资源(Locating Remote Configuration Resources) 知识点四十八:配置优先启动(ConfigFirstBootstrap) 知识点四十...

    二十二种设计模式.pdf

    三、工厂方法模式 四、建造者模式 五、适配器模式 六、桥接模式 七、组合模式 八、装饰器模式 九、外观模式 十、享元模式 十一、代理模式 十二、命令模式 十三、责任链模式 十四、解释器模式 十五、迭代器模式 十六...

    设计模式PPT.rar

    13第十三讲外观模式 14第十四讲组合模式 15第十五讲桥接模式 16第十六讲适配器模式 17第十七讲解释器模式 18第十八讲中介者模式 19第十九讲职责链模式 20第二十讲迭代模式 21第二十一讲模板方法模式 22第二十二讲...

    敏捷软件开发:原则、模式与实践

    第二十六章 PROXY模式和STAIRWAY TO HEAVEN模式:管理第三方API 第二十七章 案例研究:气象站 第Ⅵ部分 ETS案例研究 第二十八章 VISITOR模式 第二十九章 STATE模式 第三十章 ETS框架 附录 附录A UML表示法Ⅰ:CGI...

    java设计模式解释

    比如,一个应用需要处理不同类型的文件格式,但不知道具体是哪种格式,可以通过工厂方法模式来动态地选择文件处理器。 **示例:** 考虑一个场景,我们需要创建不同类型的操作系统界面组件,如按钮。通过定义一个...

    GOF-设计模式-Design Patterns-英文原版-高清-有目录-有页码

    #### 四、设计模式目录组织 **设计模式目录的组织结构:** 设计模式通常按照其解决的设计问题类型进行分类。本书将其分为三大类: 1. **创建型模式**(Creational Patterns) 2. **结构型模式**(Structural Patterns)...

    C#设计模式PDF 电子书

    十、模板方法模式(Template Method) 模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 这些设计模式是软件开发中的宝贵...

    设计模式C++版

    (五)工厂方法模式:它是工厂模式的一种,将对象的创建延迟到子类,使得子类可以在不修改父类代码的情况下,定制对象的创建过程。 (六)原型模式:原型模式通过复制已有对象来创建新对象,减少了创建新对象的开销...

    C++设计模式

    (五)工厂方法模式 11 (六)原型模式 13 (七)模板方法模式 15 迪米特法则 16 (八)外观模式 16 (九)建造者模式(生成器模式) 19 (十)观察者模式 23 (十一)抽象工厂模式 28 (十二)状态模式 32 (十三)...

    设计模式-状态模式分享ppt

    该模式的核心思想是定义一系列的状态类,并将这些状态类封装起来,使得外部客户端无需关心对象的具体状态即可调用相应的方法。 #### 三、状态模式的核心概念 - **Context(上下文)**:定义了客户感兴趣的接口,并...

    设计模式之禅之+组合模式

    #### 四、组合模式的实现 根据上面的人事架构示例,我们可以定义三个主要的接口:`IRoot`、`IBranch` 和 `ILeaf`,分别对应于根节点、树枝节点和树叶节点。每个接口都定义了获取信息的方法以及添加子节点的方法。...

    设计模式C#版

    工厂方法模式是简单工厂模式的升级版,它定义了一个创建对象的接口,但让子类决定要实例化的类是哪一个。工厂方法让类的实例化延迟到子类中进行。 十三、抽象工厂模式 抽象工厂模式提供一个接口,用于创建相关或...

    面向对象10个设计模式类图和总结

    五、工厂方法模式 定义:提供一个接口来创建对象,但让子类决定实例化哪个类。 应用条件:需要在运行时动态地选择创建哪个对象 案例:比萨饼工厂、简单工厂 类图: * Factory(工厂) + createProduct(创建...

    设计模式PPT合集

    十五、模板方法模式 模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。它使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 这个设计模式PPT合集为初学者提供了全面的学习资源...

    61条面向对象设计的经验原则

    **原则四十六:** 如果不需要频繁访问某项信息,则无需将其存储在内存中。这样做可以节省资源,并提高系统的响应速度。 **原则四十七:** 在需要处理大量数据时,考虑使用懒加载技术。这可以避免一次性加载所有数据...

    长久以来对设计模式的重大误解

    敏捷开发强调快速迭代和适应变化,而设计模式恰好提供了一种灵活应对变化的方法,如适配器模式、装饰者模式等。 误区十:不使用设计模式就是落伍。虽然设计模式不是强制性的,但对它们的理解和应用可以提高代码质量...

    设计模式解析(英文版).pdf

    《设计模式解析》书中详细介绍了十种最常用的设计模式,并分析了每种模式的特点、应用场景以及如何结合其他模式使用。这些设计模式大致可以分为以下几类: 1. **创建型模式**:关注对象的创建方式,例如单例模式、...

    C# 设计模式(用常用的设计模式编写C#程序)

    模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中。C#中的抽象类和虚方法是实现该模式的基础。 十二、状态模式 状态模式允许对象在其内部状态改变时改变它的行为,对象看起来似乎改变了它的类。...

Global site tag (gtag.js) - Google Analytics