Java设计模式(十四)----模板方法模式

模板方法模式
一、概述
二、结构
三、具体案例
四、优缺点和设计思想



一、概述
模板方法模式是类的行为模式。准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。这就是模板方法模式的用意

二、结构
 模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代码复用的基本技术。
  模板方法模式需要开发抽象类和具体子类的设计师之间的协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻 辑步骤。代表这些具体逻辑步骤的方法称做基本方法(primitive method);而将这些基本方法汇总起来的方法叫做模板方法(template method),这个设计模式的名字就是从此而来。
  模板方法所代表的行为称为顶级行为,其逻辑称为顶级逻辑。模板方法模式的静态结构图如下所示:
  
  
  这里涉及到两个角色:
  抽象模板(Abstract Template)角色有如下责任:
  ■定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
  ■定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
  
  具体模板(Concrete Template)角色又如下责任:
  ■实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。
  ■每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
  
源代码
  抽象模板角色类,abstractMethod()、hookMethod()等基本方法是顶级逻辑的组成步骤,这个顶级逻辑由templateMethod()方法代表。

public abstract class AbstractTemplate {
    /**
     * 模板方法
     */
    public void templateMethod(){
        //调用基本方法
    abstractMethod();
        hookMethod();
        concreteMethod();
    }
    /**
     * 基本方法的声明(由子类实现)
     */
    protected abstract void abstractMethod();
    /**
     * 基本方法(空方法)
     */
    protected void hookMethod(){}
    /**
     * 基本方法(已经实现)
     */
    private final void concreteMethod(){
        //业务相关的代码    }
}

  具体模板角色类,实现了父类所声明的基本方法,abstractMethod()方法所代表的就是强制子类实现的剩余逻辑,而hookMethod()方法是可选择实现的逻辑,不是必须实现的。

public class ConcreteTemplate extends AbstractTemplate{
    //基本方法的实现    @Override
    public void abstractMethod() {
        //业务相关的代码    }
    //重写父类的方法    @Override
    public void hookMethod() {
        //业务相关的代码    }
}

  模板模式的关键是:子类可以置换掉父类的可变部分,但是子类却不可以改变模板方法所代表的顶级逻辑。
  
  每当定义一个新的子类时,不要按照控制流程的思路去想,而应当按照“责任”的思路去想。换言之,应当考虑哪些操作是必须置换掉的,哪些操作是可以置换掉的,以及哪些操作是不可以置换掉的。使用模板模式可以使这些责任变得清晰。

模板方法中的方法
  模板方法中的方法可以分为两大类:模板方法和基本方法
  
模板方法
  一个模板方法是定义在抽象类中的,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。
  一个抽象类可以有任意多个模板方法,而不限于一个。每一个模板方法都可以调用任意多个具体方法。
基本方法

  抽象方法:一个抽象方法由抽象类声明,由具体子类实现。在Java语言里抽象方法以abstract关键字标示。
  
  具体方法:一个具体方法由抽象类声明并实现,而子类并不实现或置换。
  
  钩子方法:一个钩子方法由抽象类声明并实现,而子类会加以扩展。通常抽象类给出的实现是一个空实现,作为方法的默认实现。
  
  在上面的例子中,AbstractTemplate是一个抽象类,它带有三个方法。其中abstractMethod()是一个抽象方法,它由抽象类声明为抽象方法,并由子类实现;hookMethod()是一个钩子方法,它由抽象类声明并提供默认实现,并且由子类置换掉。 concreteMethod()是一个具体方法,它由抽象类声明并实现。
  
默认钩子方法
  一个钩子方法常常由抽象类给出一个空实现作为此方法的默认实现。这种空的钩子方法叫做“Do Nothing Hook”。显然,这种默认钩子方法在缺省适配模式里面已经见过了,一个缺省适配模式讲的是一个类为一个接口提供一个默认的空实现,从而使得缺省适配类的 子类不必像实现接口那样必须给出所有方法的实现,因为通常一个具体类并不需要所有的方法。
 

三、具体案例

本案例实现商店结账功能;该店客户分为两种 一种是普通客户:不打折 ,另一种是会员 :打五折。所以同样价格的东西他们所付的钱就不同

源代码

/**
 * 抽象模板角色
 * @author Administrator
 *
 */
public abstract class Client {
    /**
     * 模板方法  加上final 确保不会被子类修改
     * @return 返回 计算的价钱
     */
    public final double accountMoney(){
        double oldPrice=oldPrice(10000);//假设该商品原价10000
        double discount=accountDiscount();
        return oldPrice*discount;
    }
     /**
     * 基本方法(钩子方法)留给子类实现
     * 得到客户类型
     */
    protected String  doGetClienttype(){
        return null;
    }
     /**
     * 基本方法(抽象方法)留给子类实现
     * 计算折扣  不同类型的客户折扣不同
     */
    protected abstract double accountDiscount();

    /**
     * 基本方法(具体方法),已经实现
     * 计算原价
     */
    private double oldPrice(double price){
        return price;
    }

}

/**
 * 具体模板角色1
 *  普通客户类
 * @author Administrator
 *
 */
public class CommonClient extends Client {

    @Override
    public double accountDiscount() {
        return 1.0;
    }
    @Override
    public String  doGetClienttype(){
        return "普通客户";
    }
}

/**
 * 具体模板角色2
 *  会员类
 * @author Administrator
 *
 */
public class Member extends Client{

    @Override
    public double accountDiscount() {
        return 0.5;
    }
    @Override
    public String  doGetClienttype(){
        return "会员客户";
    }
}

测试类:

public class MainClass {

    public static void main(String[] args) {
        Client c=new  CommonClient();
        String clentType1=c.doGetClienttype();
        double money1=c.accountMoney();
        System.out.println("客户种类 :"+clentType1);
        System.out.println("需支付: "+money1);

        Client m=new  Member();
        String clentType2=m.doGetClienttype();
        double money2=m.accountMoney();
        System.out.println("客户种类 :"+clentType2);
        System.out.println("需支付: "+money2);
    }

}

结果:
客户种类 :普通客户
需支付: 10000.0
客户种类 :会员客户
需支付: 5000.0
四、优缺点和设计思想



优点
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。
子类实现算法的某些细节,有助于算法的扩展。
通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。

缺点
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。

设计思想:
作为模板的方法定义在父类(父类为抽象类),而方法定义使用抽象方法,实现抽象方法的是子类,要在子类实现方法,才能决定具体的操作。如果在不同的子类执行 不同实现就可以发展出不同的处理内容。不过,无论在哪个子类执行任何一种实现,处理的大致流程都还是要依照父类制定的方式。

以上内容来自平时所看书籍和网络资源整理测试所得,如有不完善之处,欢迎指正!

时间: 2024-10-30 09:58:04

Java设计模式(十四)----模板方法模式的相关文章

设计模式 ( 十九 ) 模板方法模式Template method(类行为型)

设计模式 ( 十九 ) 模板方法模式Template method(类行为型) 1.概述 在面向对象开发过程中,通常我们会遇到这样的一个问题:我们知道一个算法所需的关键步骤,并确定了这些步骤的执行顺序.但是某些步骤的具体实现是未知的,或者说某些步骤的实现与具体的环境相关. 例子1:银行业务办理流程 在银行办理业务时,一般都包含几个基本固定步骤: 取号排队->办理具体业务->对银行工作人员进行评分. 取号取号排队和对银行工作人员进行评分业务逻辑是一样的.但是办理具体业务是个不相同的,具体业务可能

举例讲解Java设计模式编程中模板方法模式的运用实例_java

模板方法模式定义为: 在一个方法中定义了一个算法的骨架或者步骤,而将一些步骤延迟到子类中去实现.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某一些步骤. 模板方法在基类中定义了一个操作的流程顺序,能够保证该步骤按序进行,有一些步骤的具体实现在基类中已经声明,而将一些变化的步骤的具体实现交给了子类去实现,从而就达到了延迟一些步骤到子类中,模板方法一个最大的好处就是能够设定一个业务流程能够按照一定严格的顺序执行,控制了整个算法的执行步骤. 这个方法将算法定义成一组步骤,其中凡是想让

设计模式 ( 十四 ) 迭代器模式Iterator(对象行为型)

1.概述 类中的面向对象编程封装应用逻辑.类,就是实例化的对象,每个单独的对象都有一个特定的身份和状态.单独的对象是一种组织代码的有用方法,但通常你会处理一组对象或者集合. 集合不一定是均一的.图形用户界面框架中的 Window 对象可以收集任意数量的控制对象 - Menu.Slider 和 Button.并且,集合的实现可以有多种方式:PHP 数字是一个集合,但也是一个散列表,一个链接列表,一个堆栈以及队列. 例子1:电视遥控器的频道遍历 2.问题 如何操纵任意的对象集合?  如一个列表(Li

【java设计模式】之 模板方法(Template Method)模式

版权声明:尊重博主原创文章,转载请注明出处哦~http://blog.csdn.net/eson_15/article/details/51323902 目录(?)[+] 1. 模板方法的一个实例         这一节主要来学习一下设计模式中的模板方法模式.我们先来看一个例子:假如现在老板让你做一个汽车的模型,要求只要完成基本功能即可,不考虑扩展性,那你会怎么做呢?我们首先会根据经验设计一个类图:        由这个类图可知,非常简单的实现了悍马车,该车有两个型号H1和H2.那现在我们开始实

详解设计模式中的模板方法模式及在C++中的使用_C 语言

模板方法模式是设计模式行为型中最简单的一种设计模式.在实际中你甚至可能经常用到,只是你自己不知道它是一种设计模式罢了. 模板方法模式定义一个操作中的算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤.角色:抽象类(AbstractClass): 定义抽象的原语操作,具体的子类将重定义它们以实现一个算法,实现一个模板方法,定义一个算法的骨架.该模板方法不仅调用原语操作,也调用定义 具体子类 (ConcreteClass): 实现原语操作以完

设计模式中的模板方法模式在Ruby中的应用实例两则_ruby专题

实例一今天你还是像往常一样来上班,一如既往地开始了你的编程工作. 项目经理告诉你,今天想在服务器端增加一个新功能,希望写一个方法,能对Book对象进行处理,将Book对象的所有字段以XML格式进行包装,这样以后可以方便与客户端进行交互.并且在包装开始前和结束后要打印日志,这样方便调试和问题定位. 没问题!你觉得这个功能简直是小菜一碟,非常自信地开始写起代码. Book对象代码如下: class Book attr_accessor :book_name, :pages, :price, :aut

设计模式 ( 十八 ) 策略模式Strategy(对象行为型)

设计模式 ( 十八 ) 策略模式Strategy(对象行为型) 1.概述         在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如查找.排序等,一种常用的方法是硬编码(Hard Coding)在一个类中,如需要提供多种查找算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的查找算法:当然也可以将这些查找算法封装在一个统一的方法中,通过if-else-或者case等条件判断语

java-23种设计模式中,模板方法模式体现了什么原则,求大神

问题描述 23种设计模式中,模板方法模式体现了什么原则,求大神 百度上看到有人说是 单一职责原则和开放封闭原则.开放封闭原则我懂,可是单一职责原则真的有吗?子类继承了父类,实现父类的方法中的具体操作,不同的子类类型有不同的实现方式,这好像不是单一职责原则的意义啊.还是说体现了其他原则?求大神,谢谢各路英雄好汉 解决方案 1)模板方法模式是一种类的行为型模式,在它的结构图中只有类之间的继承关系,没有对象关联关系. 2)板方法模式是基于继承的代码复用基本技术,模板方法模式的结构和用法也是面向对象设计

Java设计模式之中介者模式(Mediator Pattern)简介_java

Java设计模式的中介者模式是行为模式之一.定义一个中介对象来封装系列对象之间的交互.中介者使各个对象不需要显式地相互引用,从而使其耦合性松散,并且可以独立地改变他们之间的交互. 如下图所示: 生产者.消费者.代理商之间的中介模式实例: public abstract class PersonColleague { protected Mediator mediator; public Mediator getMediator() { return mediator; } public void

java设计模式之简单工厂模式

在编写一个计算器程序时,可以将业务逻辑和显示分离,业务逻辑封装为一个类(封装):如果要新添加一种运算,可以先创建一个Operation的基类,然后各种运算从Operation类继承,并实现GetResult()虚函数,这时添加新的运算只需要派生一个新的类,即不需要之前的运算参与编译.如何让计算器知道我是希望使用哪种运算呢?应该考虑单独的类来做这个创造实例的过程,这就是工厂.创建一个OperationFactory类,传入参数,函数createOperate就可以实例化出合适的对象. Java代码