
一个最纯粹的技术分享网站,打造精品技术编程专栏!编程进阶网
关于设计模式,所有的代码都放到了该项目。设计模式大全
模版模式是一种行为设计模式,它定义了一个操作中的算法骨架,而将一些步骤延迟到子类中实现。这种方式让子类可以在不改变算法结构的情况下重新定义算法的某些特定步骤。文章详细介绍了模版模式的基础概念、应用场景、实现原理及优缺点,并通过具体案例深入解析了模版模式的使用方法。适合初学者和有一定经验的开发者深入学习。
在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。
如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或者晚期实现需求?如何保证架构逻辑的正常执行,而不被子类破坏 ?这个时候可以用模版模式!
模板方法模式是类的行为模式。
模板模式(Template)将定义的算法抽象成一组步骤,在抽象类种定义算法的骨架,把具体的操作留给子类来实现。
模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
常见模板模式运用场景如下:
总结:当存在一些通用的方法,可以在多个子类中共用时。
实际开发中常常会遇到,代码骨架类似甚至相同,只是具体的实现不一样的场景。
例如:休假流程都有开启、编辑、驳回、结束。共享单车都是先开锁、骑行、上锁、付款。每个流程都包含这几个步骤,不同的是不同的流程实例它们的内容不一样。你该如何设计?
模板模式的主要特点包括:
解决在多个子类中重复实现相同的方法的问题,通过将通用方法抽象到父类中来避免代码重复。
以生活中买菜做饭的例子来写个Demo,烧饭一般都是买菜、洗菜、烹饪、装盘四大过程。中国自古有八大菜系,制作方式肯定都避不开这四个过程。那在模板模式中如何实现呢?
这些大的步骤固定,不同的是每个实例的具体实现细节不一样。这些类似的业务我们都可以使用模板模式实现。
关于实现买菜做饭,做川菜和徽菜。最原始的实现如下所示:
private void cook() {
System.out.println("----------川菜制作------------");
Cooking chuanCaiService = new Cooking(0);
chuanCaiService.process();
System.out.println("-----------徽菜制作-----------");
Cooking huiCaiService = new Cooking(1);
huiCaiService.process();
}
public class Cooking {
//type是0表示川菜
//type是1表示徽菜
private int type;
public Cooking(int type) {
this.type = type;
}
public void process() {
shopping();
wash();
cooking();
dishedUp();
}
protected void shopping() {
if (type == 0) {
System.out.println("买菜:黑猪肉一斤,蒜头5个");
} else if (type == 1){
System.out.println("买菜:新鲜鱼一条,红辣椒五两");
}
}
protected void wash() {
if (type == 0) {
System.out.println("清洗:猪肉洗净,蒜头去皮");
} else if (type == 1){
System.out.println("清洗:红椒洗净切片,鱼头半分");
}
}
protected void cooking() {
if (type == 0) {
System.out.println("烹饪:大火翻炒,慢火闷油");
} else if (type == 1){
System.out.println("装盘:用长形盘子装盛");
}
}
protected void dishedUp() {
if (type == 0) {
System.out.println("装盘:深碗盛起,热油浇拌");
} else if (type == 1){
System.out.println("烹饪:鱼头水蒸,辣椒过油");
}
}
}你有没有发现这样写,要是后期在拓展一个鲁菜,粤菜。这样就会修改原代码,会破坏代码的开闭原则。或者我想修改一下不同菜系的做菜步骤,那就导致代码非常难以修改。
创建一个抽象类,它的模板方法被设置为 final。为防止恶意操作,一般模板方法都加上 final 关键词。
public abstract class AbstractCookingService {
//买菜
protected abstract void shopping();
//清洗
protected abstract void wash();
//烹饪
protected abstract void cooking();
//装盘
protected abstract void dishedUp();
public final void process() {
shopping();
wash();
cooking();
dishedUp();
}
}创建实现了上述抽象类的子类。
/**
* 徽菜制作大厨
*/
public class HuiCaiChef extends AbstractCookingService {
@Override
protected void shopping() {
System.out.println("买菜:新鲜鱼一条,红辣椒五两");
}
@Override
protected void wash() {
System.out.println("清洗:红椒洗净切片,鱼头半分");
}
@Override
protected void cooking() {
System.out.println("烹饪:鱼头水蒸,辣椒过油");
}
@Override
protected void dishedUp() {
System.out.println("装盘:用长形盘子装盛");
}
}
/**
* 川菜制作大厨
*/
public class ChuanCaiChef extends AbstractCookingService {
@Override
protected void shopping() {
System.out.println("买菜:黑猪肉一斤,蒜头5个");
}
@Override
protected void wash() {
System.out.println("清洗:猪肉洗净,蒜头去皮");
}
@Override
protected void cooking() {
System.out.println("烹饪:大火翻炒,慢火闷油");
}
@Override
protected void dishedUp() {
System.out.println("装盘:深碗盛起,热油浇拌");
}
}然后测试演示一下
private void test() {
System.out.println("----------川菜制作------------");
AbstractCookingService chuanCaiService = new ChuanCaiChef();
chuanCaiService.process();
System.out.println("-----------徽菜制作-----------");
AbstractCookingService huiCaiService = new HuiCaiChef();
huiCaiService.process();
}在模板模式中,定义了一个算法的框架,将算法的具体步骤延迟到子类中实现。这种模式允许子类重写算法的特定步骤而不改变算法的结构。
模板模式中通常包含两个角类,一个模板类和一个具体类,模板类就是一个算法框架。
模板模式也没什么高深莫测的,简单来说就是三大步骤:
模板模式的主要角色包括:
抽象类(Abstract):定义了算法骨架,包含一个或多个抽象方法,这些方法由子类来具体实现。抽象类中通常还包含一个模板方法,用来调用抽象方法和具体方法,控制算法的执行顺序;还可以定义钩子方法,用于在算法中进行条件控制。
具体类(Concrete Class):继承抽象类,实现抽象方法。
以订外卖为例,解释一下模板模式。假设订外卖的过程包含三个步骤:选择外卖、支付、取外卖、是否打赏。
我们可以定义一个OderFood的抽象类,那么选择外卖就可以是抽象方法,需要子类取实现它,支付和取外卖可以定义为具体方法,另外是否打赏为钩子方法,子类可以决定是否对算法的不同进行挂钩。
还需要定义一个模板方法,用以控制流程;不同的商家,如KFC、星巴克就是具体类。
OrderFood——抽象类(Abstract)
/**
* @author Created by njy on 2023/6/24
* 1.抽象类(Abstract Class):点外卖
* 包含选择外卖、支付、取外卖三个方法,
* 其中选择外卖为抽象方法,需要子类实现
* 支付、取外卖为具体方法
* 另外是否打赏为钩子方法,子类可以决定是否对算法的不同进行挂钩
*/
public abstract class OrderFood {
//模板方法
public void order(){
selectFood();
pay();
getFood();
}
//选择外卖 抽象方法 由子类实现具体细节
public abstract void selectFood();
//是否打赏 钩子方法 可以重写来做条件控制
public boolean isGiveAward(){
return false;
}
//-------具体方法----------
public void pay(){
System.out.println("支付成功,外卖小哥正在快马加鞭~~");
}
//取外卖
public void getFood(){
System.out.println("取到外卖");
if (isGiveAward()){
System.out.println("打赏外卖小哥");
}
}
}具体类(Concrete Class)
/**
* 具体类(Concrete Class):星巴克
*/
public class Starbucks extends OrderFood{
//实现父类方法
@Override
public void selectFood() {
System.out.println("一杯抹茶拿铁");
}
//重写钩子方法,打赏外卖小哥
@Override
public boolean isGiveAward(){
return true;
}
}
/**
* 具体类(Concrete Class):KFC
*/
public class KFC extends OrderFood{
@Override
public void selectFood() {
System.out.println("一份汉堡炸鸡四件套");
}
}测试一下,代码如下:
//星巴克(重写了钩子方法,打赏外卖小哥)
OrderFood orderFood=new Starbucks();
orderFood.order();
System.out.println("--------KFC------------");
//KFC
OrderFood orderFood1=new KFC();
orderFood1.order();注意事项:为了防止恶意修改,模板方法通常使用final关键字修饰,避免被子类重写。
需求1: 实现字符打印和字符串打印两种不同的打印样式。
分析和实现:定义一个抽象类AbstractDisplay其中包含模板方法display,两个实现模板的具体类,CharDisplay和StringDisplay。具体可以看:TemplateDesign
需求2: 做菜的步骤一般是:洗锅 --> 炒菜 --> 洗碗 ,不同的菜,只是炒菜这一个步骤具体细节是不同的。然后做一个煮糖醋鲤鱼,小炒肉,你该如何实现?
分析和实现:整体流程是一样的,有些步骤一样,有些步骤不一样,但是不使用模板模式,需要每个类都重写一遍方法,这个时候可以用模版模式实现。具体可以看:TemplateDesign
模块 | 描述 | 备注 |
|---|---|---|
GitHub | 多个YC系列开源项目,包含Android组件库,以及多个案例 | |
博客汇总 | 汇聚Java,Android,C/C++,网络协议,算法,编程总结等 | |
设计模式 | 六大设计原则,23种设计模式,设计模式案例,面向对象思想 | |
Java进阶 | 数据设计和原理,面向对象核心思想,IO,异常,线程和并发,JVM | |
网络协议 | 网络实际案例,网络原理和分层,Https,网络请求,故障排查 | |
计算机原理 | 计算机组成结构,框架,存储器,CPU设计,内存设计,指令编程原理,异常处理机制,IO操作和原理 | |
学习C编程 | C语言入门级别系统全面的学习教程,学习三到四个综合案例 | |
C++编程 | C++语言入门级别系统全面的教学教程,并发编程,核心原理 | |
算法实践 | 专栏,数组,链表,栈,队列,树,哈希,递归,查找,排序等 | |
Android | 基础入门,开源库解读,性能优化,Framework,方案设计 |
23种设计模式
23种设计模式 & 描述 & 核心作用 | 包括 |
|---|---|
创建型模式 提供创建对象用例。能够将软件模块中对象的创建和对象的使用分离 | 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern) |
结构型模式 关注类和对象的组合。描述如何将类或者对象结合在一起形成更大的结构 | 适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式(Flyweight Pattern) 代理模式(Proxy Pattern) |
行为型模式 特别关注对象之间的通信。主要解决的就是“类或对象之间的交互”问题 | 责任链模式(Chain of Responsibility Pattern) 命令模式(Command Pattern) 解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式(Null Object Pattern) 策略模式(Strategy Pattern) 模板模式(Template Pattern) 访问者模式(Visitor Pattern) |
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。