Carson带你学设计模式:模板方法模式(Template Method)

前言

今天Carson来全面总结最常用的设计模式 - 模板方法模式。

Carson带你学设计模式系列文章
Carson带你学设计模式:这是一份全面 & 详细的设计模式学习指南
Carson带你学设计模式:单例模式(Singleton)
Carson带你学设计模式:简单工厂模式(SimpleFactoryPattern)
Carson带你学设计模式:工厂方法模式(Factory Method)
Carson带你学设计模式:抽象工厂模式(Abstract Factory)
Carson带你学设计模式:建造者模式(Builder Pattern)
Carson带你学设计模式:适配器模式(Adapter Pattern)
Carson带你学设计模式:外观模式(Facade Pattern)
Carson带你学设计模式:静态代理模式(Proxy Pattern)
Carson带你学设计模式:动态代理模式(Proxy Pattern)
Carson带你学设计模式:模板方法模式(Template Method)
Carson带你学设计模式:策略模式(Strategy Pattern)
Carson带你学设计模式:观察者模式(Observer)


目录

模板方法模式.jpg


1. 介绍

1.1 定义

定义一个模板结构,将具体内容延迟到子类去实现。

1.2 主要作用

在不改变模板结构的前提下在子类中重新定义模板中的内容。

模板方法模式是基于”继承“的;

1.3 解决的问题

  • 提高代码复用性
    将相同部分的代码放在抽象的父类中,而将不同的代码放入不同的子类中
  • 实现了反向控制
    通过一个父类调用其子类的操作,通过对子类的具体实现扩展不同的行为,实现了反向控制 & 符合“开闭原则”

2. 模式原理

2.1 UML类图 & 组成

UML类图

2.2 实例讲解

接下来我用一个实例来对模板方法模式进行更深一步的介绍。
a. 实例概况

  • 背景:小成希望学炒菜:手撕包菜 & 蒜蓉炒菜心
  • 冲突:两道菜的炒菜步骤有的重复有的却差异很大,记不住
  • 解决方案:利用代码记录下来

b. 使用步骤
步骤1: 创建抽象模板结构(Abstract Class):炒菜的步骤


public  abstract class Abstract Class {  
//模板方法,用来控制炒菜的流程 (炒菜的流程是一样的-复用)
//申明为final,不希望子类覆盖这个方法,防止更改流程的执行顺序 
        final void cookProcess(){  
        //第一步:倒油
        this.pourOil();
        //第二步:热油
         this.HeatOil();
        //第三步:倒蔬菜
         this.pourVegetable();
        //第四步:倒调味料
         this.pourSauce();
        //第五步:翻炒
         this.fry();
    }  

//定义结构里哪些方法是所有过程都是一样的可复用的,哪些是需要子类进行实现的

//第一步:倒油是一样的,所以直接实现
void pourOil(){  
        System.out.println("倒油");  
    }  

//第二步:热油是一样的,所以直接实现
    void  HeatOil(){  
        System.out.println("热油");  
    }  

//第三步:倒蔬菜是不一样的(一个下包菜,一个是下菜心)
//所以声明为抽象方法,具体由子类实现 
    abstract void  pourVegetable();

//第四步:倒调味料是不一样的(一个下辣椒,一个是下蒜蓉)
//所以声明为抽象方法,具体由子类实现 
    abstract void  pourSauce();


//第五步:翻炒是一样的,所以直接实现
    void fry();{  
        System.out.println("炒啊炒啊炒到熟啊");  
    }  
}

步骤2: 创建具体模板(Concrete Class),即”手撕包菜“和”蒜蓉炒菜心“的具体步骤

//炒手撕包菜的类
  public class ConcreteClass_BaoCai extend  Abstract Class{
    @Override
    public void  pourVegetable(){  
        System.out.println(”下锅的蔬菜是包菜“);  
    }  
    @Override
    public void  pourSauce(){  
        System.out.println(”下锅的酱料是辣椒“);  
    }  
}
//炒蒜蓉菜心的类
  public class ConcreteClass_CaiXin extend  Abstract Class{
    @Override
    public void  pourVegetable(){  
        System.out.println(”下锅的蔬菜是菜心“);  
    }  
    @Override
    public void  pourSauce(){  
        System.out.println(”下锅的酱料是蒜蓉“);  
    }  
}

步骤3:客户端调用-炒菜了

public class Template Method{
  public static void main(String[] args){

//炒 - 手撕包菜
    ConcreteClass_BaoCai BaoCai = new ConcreteClass_BaoCai();
    BaoCai.cookProcess();

//炒 - 蒜蓉菜心
  ConcreteClass_ CaiXin = new ConcreteClass_CaiXin();
    CaiXin.cookProcess();
    }
        
}
   

结果输出

倒油
热油
下锅的蔬菜是包菜
下锅的酱料是辣椒
炒啊炒啊炒到熟

倒油
热油
下锅的蔬菜是菜心
下锅的酱料是蒜蓉
炒啊炒啊炒到熟

通过上述这个常见的生活例子,我相信你已经完全明白了模板方法模式的原理了!!


3. 优缺点

在全面解析完模板方法模式后,我来分析下其优缺点:

3.1 优点

  • 提高代码复用性
    将相同部分的代码放在抽象的父类中
  • 提高了拓展性
    将不同的代码放入不同的子类中,通过对子类的扩展增加新的行为
  • 实现了反向控制
    通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,实现了反向控制 & 符合“开闭原则”

3.2 缺点

引入了抽象类,每一个不同的实现都需要一个子类来实现,导致类的个数增加,从而增加了系统实现的复杂度。


4. 应用场景

  • 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现;
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复;
  • 控制子类的扩展。

5. 总结

本文主要对模板方法模式进行了全面介绍。


欢迎关注Carson_Ho的优快云博客 与 公众号!

博客链接:https://carsonho.blog.youkuaiyun.com/


请帮顶 / 评论点赞!因为你的鼓励是我写作的最大动力!

当执行 `rpm -ivh containerd.io-1.2.6-3.3.el7.x86_64.rpm docker-ce-19.03.9-3.el7.x86_64.rpm container-selinux-2.119.2-1.911c772.el7_8.noarch.rpm docker-ce-cli-19.03.9-3.el7.x86_64.rpm --force --nodeps` 命令出现 '头V4 RSA/SHA512 Signature, 密钥' 报错时,可参考已有引用中的相关思路来解决: ### 缺少密钥问 若报错为 `NOKEY`,通常是缺少RPM包的签名密钥。可以导入对应的签名密钥来解决。 以引用中的 `key ID 621e9f35` 为例,可执行如下命令导入密钥: ```bash rpm --import https://download.docker.com/linux/centos/gpg ``` ### 依赖问 执行 `--force --nodeps` 虽然可跳过依赖检查,但可能导致后续使用时出现问。若遇到像引用中提到的依赖问,需针对性解决: - **containerd.io版本问**:若提示 `containerd.io` 版本太旧,可下载合适的 `containerd.io` 包进行更新。如引用中提供的链接: ```bash wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm ``` - **缺少 `docker-ce-cli` 依赖**:可下载并安装 `docker-ce-cli` 包: ```bash wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-cli-19.03.9-3.el7.x86_64.rpm ``` - **冲突问**:若遇到像 `runc` 与 `containerd.io` 冲突的情况,可删除 `runc` 及其依赖后重装: ```bash yum erase runc rpm -ivh containerd.io-1.2.6-3.3.el7.x86_64.rpm ``` 然后再安装 `docker-ce`: ```bash yum install -y docker-ce ``` ### 检查包完整性 确保下载的RPM包没有损坏。可通过比较下载包的哈希值与官方提供的哈希值来验证。 ### 重新下载包 若包已损坏,可从官方源重新下载: ```bash wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-19.03.9-3.el7.x86_64.rpm wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/container-selinux-2.119.2-1.911c772.el7_8.noarch.rpm wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-cli-19.03.9-3.el7.x86_64.rpm ```
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值