Java模板方法模式(Template Method)

来源:互联网 发布:网络策划推手哪里找 编辑:程序博客网 时间:2024/05/27 18:17
一、概念
      定义一个算法的骨架,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方法实现这些抽象方法,从而对剩余的逻辑有不同的实现。意图:在一个方法中实现一个算法,并推迟定义算法中的某些步骤,从而让子类重新定义它们。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。
      抽象类的任务是搭建逻辑的框架,通常由经验丰富的人员编写,因为抽象类的好坏直接决定了程序是否稳定性。实现类用来实现细节。抽象类中的模版方法正是通过实现类扩展的方法来完成业务逻辑。只要实现类中的扩展方法通过了单元测试,在模版方法正确的前提下,整体功能一般不会出现大的错误。

二、模式结构与参与者


抽象模板(Abstract Template)角色
     (1)定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
     (2)定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
具体模板(Concrete Template)角色
     (1)实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。
     (2)每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法的不同实现,从而使得顶级逻辑的实现各不相同。
三、模式中的方法种类
       模版方法模式由一个抽象类和一个(或一组)实现类通过继承结构组成,抽象类中的方法分为三种:
       ① 抽象方法:父类中只声明但不加以实现,而是定义好规范,然后由它的子类去实现;
       ② 模版方法(具体方法):由抽象类声明并加以实现,把基本操作方法组合在一起形成一个总算法或一个总行为的方法。一般来说,模版方法调用抽象方法来完成主要的逻辑功能,模版方法大多会定义为final类型,指明主要的逻辑功能在子类中不能被重写。子类可以置换掉父类的可变部分,但是子类却不可以改变模板方法所代表的顶级逻辑。另外,一个抽象类可以有任意多个模板方法每一个模板方法都可以调用任意多个具体方法。
      ③ 钩子方法:由抽象类声明并加以实现。但是子类可以去扩展,子类可以通过扩展钩子方法来影响模版方法的逻辑。通常抽象类给出的实现是一个空实现,作为方法的默认实现。

四、示例程序

//抽象类,充当模板角色 public abstract class AbstractDisplay {// 钩子方法public void open(){}// 由子类实现的抽象方法public abstract void print();public abstract void close();// 抽象类实现的方法,final可以保证在子类不会被修改,模板方法public final void display() {open();for (int i = 0; i < 5; i++) {print();}close();}}
public class CharDisplay extends AbstractDisplay {private char ch;public CharDisplay(char ch) {this.ch = ch;}@Overridepublic void open() {System.out.print("<<");}@Overridepublic void print() {System.out.print(ch + " ");}@Overridepublic void close() {System.out.println(">>");}}
public class StringDisplay extends AbstractDisplay {private String string; // 应输出的字符串private int width; // 以byte为单位所求出的字符串的"长度"public StringDisplay(String string) {this.string = string;this.width = string.getBytes().length;}public void open() { // 打印头装饰字符串printLine();}public void print() {System.out.println("|" + string + "|");}public void close() {printLine();}public void printLine() {System.out.print("+");for (int i = 0; i < width; ++i) {System.out.print("-"); // 当作线段}System.out.println("+");}}
public class Main {public static void main(String[] args) {// 建立1个有'A'的CharDisplay的对象AbstractDisplay d1 = new CharDisplay('A');// 建立1个有"Hello world"的StringDisplay的对象AbstractDisplay d2 = new StringDisplay("Hello World");// d1,d2都是AbstractDisplay的子类对象,可以调用继承到的display()方法d1.display();d2.display();}}
<<A A A A A >>+-----------+|Hello World||Hello World||Hello World||Hello World||Hello World|+-----------+
五、模版方法的优点及适用场景

     (1)容易扩展:一般来说,抽象类中的模版方法是不易反生改变的部分,而抽象方法是容易反生变化的部分,因此通过增加实现类一般可以很容易实现功能的扩展,符合开闭原则。
     (2)便于维护:对于模版方法模式来说,正是由于他们的主要逻辑相同,才使用了模版方法,假如不使用模版方法,任由这些相同的代码散乱的分布在不同的类中,维护起来是非常不方便的。
     (3)比较灵活:因为有钩子方法,因此,子类的实现也可以影响父类中主逻辑的运行。但是,在灵活的同时,由于子类影响到了父类,违反了里氏替换原则,也会给程序带来风险。这就对抽象类的设计有了更高的要求。
     (4)在多个子类拥有相同的方法,并且这些方法逻辑相同时,可以考虑使用模版方法模式。在程序的主框架相同,细节不同的场合下,也比较适合使用这种模式。
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 寄申通快递收件人电话写错了怎么办 第三方支付倒闭了用户的钱怎么办啊 京东配送日期内货没送到家怎么办 拼多多拼单不成功优惠券退吗怎么办 退货退错了不发回来怎么办 商家总是不发退货地址过来怎么办 美团外卖下单后电话没改怎么办 从日本邮寄东西到中国被扣怎么办 淘宝拒收卖家收到货不退款怎么办 拒收的快递丢了卖家拒绝退款怎么办 京东买了东西超过七天想退货怎么办 微信买东西支付宝付款被骗怎么办 京东购物己付款卖家没发货怎么办 天猫先行退款卖家拒收怎么办 京东金条提前还款借不了怎么办 网银密码输入六次错误怎么办 迷失在时间和空间的交界处该怎么办 用卫生巾过后瘙痒起疹子了怎么办 装修公司倒闭了装修保修卡怎么办 丈夫把妻子的车抵押出去了怎么办 亚马逊海外购超过两万的额度怎么办 增值税申报表进项税转出忘填怎么办 一般纳税人注册下来后未营业怎么办 增值税税率把3错开成了5怎么办 在义乌做压痕加工老板拖欠钱怎么办 蓝洞棋牌是赌博输了几万怎么办 夏季来月经用卫生巾外阴瘙痒怎么办 用洗衣机洗衣服忘掏卫生纸了怎么办 剖腹产后一个月了还有血怎么办 剖腹产两个月同房后下面有血怎么办 剖腹产后月子里便秘有血怎么办 产后10天b超检查有血块怎么办 吃完优思明月经没有血块怎么办 刨腹产妇42天还有恶露怎么办 打完孩子第五天同房了出血了怎么办 打完孩子同房了出了一点血怎么办 宫腔镜检查一个月同房流血多怎么办 宫颈活检后三天同房有出血怎么办 顺产侧切两个月之后同房感染怎么办 顺产40天还有暗红色的恶露怎么办 来姨妈了没带卫生棉条去游泳怎么办