设计模式--模板方法模式(TemplateMethod)

一 引入

豆浆制作有固定的步骤:选材–》添加配料–》浸泡–》放到豆浆机打碎
除了添加配料在不同口味豆浆中的操作不一样外,其他步骤在每次制作过程中都是一样的
这里就可以通过我们的模板方法实现
在这里插入图片描述
模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

二 模板方法类图

在这里插入图片描述

  1. AbstractClass 抽象类, 类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象方法operationr2,3,4
  2. ConcreteClass 实现抽象方法operationr2,3,4, 以完成算法中特点子类的步骤

三 代码实现

定义模板抽象类

public abstract class SoyaMilk {

    /**
     * 制备豆浆 通过final修饰防止子类覆写
     */
    public final void make(){
        selectSoya();
        addCondiments();
        soak();
        beat();
    }

    /**
     * 选择材料
     */
    public void selectSoya(){
        System.out.println("选择大豆");
    }

    /**
     * 加入材料 交由子类实现
     */
    public abstract void addCondiments();

    /**
     * 浸泡原料
     */
    public void soak(){
        System.out.println("浸泡原料");
    }

    /**
     * 打碎原料
     */
    public void beat(){
        System.out.println("打碎原料");
    }
}

定义抽象模板实现

public class PeanutSoyaMilk extends SoyaMilk{
    @Override
    public void addCondiments() {
        System.out.println("添加美味的花生酱。。。");
    }
}

public class SugarSoyaMilk extends SoyaMilk{
    @Override
    public void addCondiments() {
        System.out.println("添加美味的糖果...");
    }
}

客户端调用

public class Client {
    public static void main(String[] args) {
        System.out.println("制备糖果豆浆");
        SoyaMilk sugarSoyaMilk = new SugarSoyaMilk();
        sugarSoyaMilk.make();


        System.out.println("制备花生豆浆");
        SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
        peanutSoyaMilk.make();

    }
}

运行结果:

制备糖果豆浆
选择大豆
添加美味的糖果...
浸泡原料
打碎原料
制备花生豆浆
选择大豆
添加美味的花生酱。。。
浸泡原料
打碎原料

四 模板方法模式的钩子方法

在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”。

package com.yxj.template.improve;

//抽象类,表示豆浆
public abstract class SoyaMilk {

	//模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
	final void make() {
		
		select(); 
		if(customerWantCondiments()) {
			addCondiments();
		}
		soak();
		beat();
		
	}
	
	//选材料
	void select() {
		System.out.println("第一步:选择好的新鲜黄豆  ");
	}
	
	//添加不同的配料, 抽象方法, 子类具体实现
	abstract void addCondiments();
	
	//浸泡
	void soak() {
		System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");
	}
	 
	void beat() {
		System.out.println("第四步:黄豆和配料放到豆浆机去打碎  ");
	}
	
	//钩子方法,决定是否需要添加配料
	boolean customerWantCondiments() {
		return true;
	}
}


package com.yxj.template.improve;

public class PeanutSoyaMilk extends SoyaMilk {

	@Override
	void addCondiments() {
		// TODO Auto-generated method stub
		System.out.println(" 加入上好的花生 ");
	}

}


package com.yxj.template.improve;

public class RedBeanSoyaMilk extends SoyaMilk {

	@Override
	void addCondiments() {
		// TODO Auto-generated method stub
		System.out.println(" 加入上好的红豆 ");
	}

}


package com.yxj.template.improve;

public class PureSoyaMilk extends SoyaMilk{

	@Override
	void addCondiments() {
		// TODO Auto-generated method stub
		//空实现
	}
	
	@Override
	boolean customerWantCondiments() {
		// TODO Auto-generated method stub
		return false;
	}
 
}


package com.yxj.template.improve;

public class Client {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//制作红豆豆浆
		
		System.out.println("----制作红豆豆浆----");
		SoyaMilk redBeanSoyaMilk = new RedBeanSoyaMilk();
		redBeanSoyaMilk.make();
		
		System.out.println("----制作花生豆浆----");
		SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
		peanutSoyaMilk.make();
		
		System.out.println("----制作纯豆浆----");
		SoyaMilk pureSoyaMilk = new PureSoyaMilk();
		pureSoyaMilk.make();
	}

}


五 总结

优点:

1.可以提取公共的代码(选材,浸泡)这种公共的都是通过父类来定义而子类只需要继承。

2.同时扩展性强,需要整个更改流程的时候只需要更改模板,同时父类只需要定义顺序,子类来实现具体的内容。

缺点:

1.子类在做继承的时候必须要注意父类的具体顺序

2.如果模板中需要插入新的步骤,此时所有子类都需要进行实现(即使某些子类并不需要)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值