精华内容
下载资源
问答
  • 模板模式
    千次阅读
    2019-09-25 20:31:40

    在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。

    介绍

    意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

    主要解决:一些方法通用,却在每一个子类都重新写了这一方法。

    何时使用:有一些通用的方法。

    如何解决:将这些通用算法抽象出来。

    关键代码:在抽象类实现,其他步骤在子类实现。

    应用实例 :1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。 3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。

    优点 :1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。

    缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

    使用场景 :1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。

    注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。

    实现

    我们将创建一个定义操作的 Game 抽象类,其中,模板方法设置为 final,这样它就不会被重写。CricketFootball 是扩展了 Game 的实体类,它们重写了抽象类的方法。

    TemplatePatternDemo,我们的演示类使用 Game 来演示模板模式的用法。

    模板模式

    步骤 1

    创建一个抽象类,它的模板方法被设置为 final。

    Game.java

    public abstract class Game {
    
        abstract void initialize();
    
        abstract void startPlay();
    
        abstract void endPlay();
    
        //模板
        public final void play() {
            //初始化游戏
            initialize();
    
            //开始游戏
            startPlay();
    
            //结束游戏
            endPlay();
        }
    
    }
    

    步骤 2

    创建扩展了上述类的实体类。

    Cricket.java

    public class Cricket extends Game {
    
        @Override
        void endPlay() {
            System.out.println("Cricket Game Finished!");
        }
    
        @Override
        void initialize() {
            System.out.println("Cricket Game Initialized! Start playing.");
        }
    
        @Override
        void startPlay() {
            System.out.println("Cricket Game Started. Enjoy the game!");
        }
    }
    

    Football.java

    public class Football extends Game {
    
        @Override
        void endPlay() {
            System.out.println("Football Game Finished!");
        }
    
        @Override
        void initialize() {
            System.out.println("Football Game Initialized! Start playing.");
        }
    
        @Override
        void startPlay() {
            System.out.println("Football Game Started. Enjoy the game!");
        }
    
    }
    

    步骤 3

    使用 Game 的模板方法 play() 来演示游戏的定义方式。

    TemplatePatternDemo.java

    public class TemplatePatternDemo {
    
        public static void main(String[] args) {
            Game game = new Cricket();
            game.play();
            System.out.println();
    
            game = new Football();
            game.play();
        }
    
    }
    

    步骤 4

    验证输出。

    Cricket Game Initialized! Start playing.
    Cricket Game Started. Enjoy the game!
    Cricket Game Finished!
    
    Football Game Initialized! Start playing.
    Football Game Started. Enjoy the game!
    Football Game Finished!
    
    更多相关内容
  • 主要介绍了Java设计模式之模板模式(Template模式)介绍,定义一个操作中算法的骨架,将一些步骤的执行延迟到其子类中,需要的朋友可以参考下
  • 模板模式 模板模式示例 在模板模式中,抽象类公开定义的方式/模板来执行其方法。 它的子类可以根据需要重写方法的实现,但是调用的方式应与抽象类所定义的方式相同。 此模式属于行为模式类别。 执行 我们将创建一个...
  • 23个设计模式之一的模板模式,极客学院PPT源码及课件,模板模式的示例,
  • Java设计模式之模板模式

    千次阅读 2021-11-06 18:01:13
    Java设计模式之模板模式1. 模板模式概述2. 模板模式实现 1. 模板模式概述 1.模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern), 在一个抽象类公开定义了执行它的方法的模板。它的子类...

    1. 模板模式概述

    1.1 模板模式介绍

    1.模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern), 在一个抽象类公开定义了执行它的方法的模板。它的子类可以更需要重写方法实现,但可以成为典型类中定义的方式进行。
    2.简单说,模板方法模式定义了一个操作中的算法的核心定义,而将一些步骤迟缓到子类中,模仿子类可以不改变一一个算法的结构,就可以重新定义该算法的部分特定步骤。
    3.这些类型的设计模式属于行为型模式。

    模板模式适用于通用步骤的操作,比如做菜,不管你是西红柿炒鸡蛋,还是土豆炖牛肉实现步骤都是一样的,备料,做菜,上菜。
    再比如投放系统,不管你是投放巨量引擎,广点通还是百度,前期工作实现步骤也都是一样的,配置物料信息,构建投放对象,投放广告。

    1.2 模板模式类图

    在这里插入图片描述
    对原理类图的说明-即(模板方法模式的角色及职责)
    1.AbstractClass 抽象类, 类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象方法。
    2.ConcreteClass 实现抽象方法, 以完成算法中特点子类的步骤。

    1.3 模板方法模式的注意事项和细节

    1. 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改.需要修改算法时,只要修改父类的模板方 法或者已经实现的某些步骤,子类就会继承这些修改
    2. 实现了最大化代码复用.父类的模板方法和已实现的某些步骤会被子类继承而直接使用.
    3. 既统一了算法,也提供了很大的灵活性.父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步 骤的实现.
    4. 该模式的不足之处:每个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大
    5. 一般模板方法都加上 final 关键字, 防止子类重写模板方法.
    6. 模板方法模式使用场景:当要完成在某个过程,该过程要执行一系列步骤 ,这一系列的步骤基本相同,但其 个别步骤在实现时 可能不同,通常考虑用模板方法模式来处理

    2. 模板模式实现

    模板模式实现案例采用三种方式:
    第一案例是做菜,无论做什么菜都是这三个步骤,备料,做菜,上菜,但是三个步骤都不相同,模板定义步骤流程,通过不同的子类继承抽象模板实现模板设计模式。

    第二个案例是银行办理业务,无论办理什么业务都是取号,办理业务,评价。这里取号与评价都是相同的,各个子类只需要处理不同业务即可,通过不同的子类继承抽象模板实现模板设计模式。

    第三个案例是银行办理业务的Java8函数式编程消费者模式Consumer模式改造,原理相同。

    2.1 做菜模板模式

    DishEggsWithTomato

    package com.zrj.design.template.dish;
    
    /**
     * 西红柿炒鸡蛋
     *
     * @author zrj
     * @since 2022/2/8
     */
    public class DishEggsWithTomato extends DishTemplate {
        @Override
        public void preparation() {
            System.out.println("准备西红柿鸡蛋...");
        }
    
        @Override
        public void doing() {
            System.out.println("开始炒西红柿鸡蛋...");
        }
    
        @Override
        public void carriedDishes() {
            System.out.println("西红柿鸡蛋装盘...");
        }
    }
    
    
    

    DishOnionWithTofu

    package com.zrj.design.template.dish;
    
    
    /**
     * 小葱拌豆腐
     *
     * @author zrj
     * @since 2022/2/8
     */
    public class DishOnionWithTofu extends DishTemplate {
        @Override
        public void preparation() {
            System.out.println("准备小葱豆腐...");
        }
    
        @Override
        public void doing() {
            System.out.println("开始炒小葱拌豆腐...");
        }
    
        @Override
        public void carriedDishes() {
            System.out.println("小葱拌豆腐装盘...");
        }
    }
    
    
    
    

    DishTemplate

    package com.zrj.design.template.dish;
    
    /**
     * 做菜模板类
     * 用于定义做菜的执行步骤,所有菜都可以按照这种方式做菜
     *
     * @author zrj
     * @since 2022/2/8
     */
    public abstract class DishTemplate {
        /**
         * 做菜执行步骤
         */
        public final void doDish() {
            this.preparation();
            this.doing();
            this.carriedDishes();
        }
    
        /**
         * 备料
         */
        public abstract void preparation();
    
        /**
         * 做菜
         */
        public abstract void doing();
    
        /**
         * 上菜
         */
        public abstract void carriedDishes();
    
    }
    
    
    
    

    DishTemplateTest

    package com.zrj.design.template.dish;
    
    
    import org.junit.Test;
    
    /**
     * 模板模式
     * 抽象父类定义方法模板,子类自定义实现方式。
     * 优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
     * 缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
     * 使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
     * 注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。
     *
     * 使用场景很多,只要有相同的执行逻辑,或者重要的复杂的方法,都可以交给父类管理。
     * 比如开发XX系统步骤都是一样的,立项,需求,开发,测试,上线。
     *
     * @author zrj
     * @since 2022/2/8
     */
    public class DishTemplateTest {
        @Test
        public void templateTest() {
            System.out.println("----------西红柿炒鸡蛋----------");
            DishTemplate eggsWithTomato = new DishEggsWithTomato();
            eggsWithTomato.doDish();
    
            System.out.println("----------小葱拌豆腐----------");
            DishTemplate onionWithTofu = new DishOnionWithTofu();
            onionWithTofu.doDish();
        }
    
    }
    
    
    

    2.2 银行办理业务模板模式

    BankBusinessHandler

    package com.zrj.design.template.bank;
    
    import cn.hutool.core.util.RandomUtil;
    
    /**
     * 模板方法设计模式的抽象类
     * 模板设计模式主要用来处理相同处理流程中的不同点,例如银行办理业务,无论什么业务,首先需要取号,其次处理业务,然后评价不同之处在于处理不同的业务使用不同的方式。
     * BankBusinessHandler作为抽象模板
     * BankSaveMoneyHandler作为存钱业务处理类,继承抽象模板BankBusinessHandler
     * BankDrawMoneyHandler作为理财业务处理类,继承抽象模板BankBusinessHandler
     *
     * @author zrj
     * @since 2022/2/8
     **/
    public abstract class BankBusinessHandler {
    
        /**
         * 模板方法,执行器
         */
        public final void execute() {
            getNumber();
            handle();
            judge();
        }
    
        /**
         * 取号
         */
        private void getNumber() {
            System.out.println("取号:" + RandomUtil.randomNumbers(8));
        }
    
        /**
         * 办理业务
         */
        public abstract void handle();
    
        /**
         * 评价
         */
        private void judge() {
            System.out.println("评价:五星好评!");
        }
    
    }
    
    

    BankBusinessHandlerTest

    package com.zrj.design.template.bank;
    
    /**
     * 模板方法测试类
     *
     * @author zrj
     * @since 2022/2/8
     **/
    public class BankBusinessHandlerTest {
        public static void main(String[] args) {
    
            //存钱业务处理
            BankSaveMoneyHandler bankSaveMoneyHandler = new BankSaveMoneyHandler();
            bankSaveMoneyHandler.execute();
    
            System.out.println("------------------------------");
    
            //理财业务处理
            BankDrawMoneyHandler bankDrawMoneyHandler = new BankDrawMoneyHandler();
            bankDrawMoneyHandler.execute();
    
        }
    }
    
    

    BankDrawMoneyHandler

    package com.zrj.design.template.bank;
    
    /**
     * 理财业务
     *
     * @author zrj
     * @since 2022/2/8
     **/
    public class BankDrawMoneyHandler extends BankBusinessHandler {
        /**
         * 办理业务
         */
        @Override
        public void handle() {
            System.out.println("理财:2000$");
        }
    }
    
    

    BankSaveMoneyHandler

    package com.zrj.design.template.bank;
    
    /**
     * 存钱业务
     *
     * @author zrj
     * @since 2022/2/8
     **/
    public class BankSaveMoneyHandler extends BankBusinessHandler {
        /**
         * 办理业务
         */
        @Override
        public void handle() {
            System.out.println("存钱:1000$");
        }
    }
    
    

    2.3 银行办理业务函数式编程改造

    BankBusinessHandlerCustomer

    package com.zrj.design.template.customer;
    
    import cn.hutool.core.util.RandomUtil;
    
    import java.math.BigDecimal;
    import java.util.function.Consumer;
    
    /**
     * 模板设计模式的抽象类
     * Java8函数式编程消费者模式Customer实现模板设计模式
     *
     * @author zrj
     * @since 2022/2/8
     **/
    public class BankBusinessHandlerCustomer {
        /**
         * 存钱
         */
        public void save(BigDecimal amount) {
            execute(a -> System.out.println("存钱:" + amount));
        }
    
        /**
         * 理财
         */
        public void draw(BigDecimal amount) {
            execute(a -> System.out.println("理财:" + amount));
        }
    
        /**
         * 模板方法,执行器
         */
        public void execute(Consumer<BigDecimal> consumer) {
            getNumber();
            consumer.accept(null);
            judge();
        }
    
        /**
         * 取号
         */
        private void getNumber() {
            System.out.println("取号:" + RandomUtil.randomNumbers(8));
        }
    
        /**
         * 评价
         */
        private void judge() {
            System.out.println("评价:五星好评!");
        }
    }
    
    

    BankBusinessHandlerCustomerTest

    package com.zrj.design.template.customer;
    
    import java.math.BigDecimal;
    
    /**
     * @author zrj
     * @since 2022/2/8
     **/
    public class BankBusinessHandlerCustomerTest {
        public static void main(String[] args) {
            //构建银行业务处理对象
            BankBusinessHandlerCustomer businessHandler = new BankBusinessHandlerCustomer();
    
            //存钱业务处理
            businessHandler.save(new BigDecimal("3000"));
    
            System.out.println("------------------------------");
    
            //理财业务处理
            businessHandler.draw(new BigDecimal("6000"));
    
        }
    
    }
    
    
    展开全文
  • java设计模式之模板模式,实例子说明模板模式的使用场景。
  • 策略模式与模板模式的区别 - Eviltuzki的个人页面 - OSCHINA - 中文开源技术交流社区.mht
  • 设计模式回顾——模板模式(C++)

    千次阅读 2020-10-24 18:22:53
    模板模式(Template Pattern),指的是定义一个抽象(算法)模板结构父类,具体实现方法由子类实现。模板模式是行为型设计模式中使用较为广泛的设计模式。


    1 前言

      上一篇文章中对“适策略模式”进行概述与总结,分别描述了策略模式含义、特点、优缺点、适用场景以及实现过程步骤,并以C++语言实现具体例子。本文描述另一常用的设计模式,而且与策略模式比较相似的设计模式——模板模式。


    相关文章:

    设计模式回顾——原型模式
    设计模式回顾——观察者模式
    设计模式回顾——模板模式
    设计模式回顾——策略模式
    设计模式回顾——适配器模式
    设计模式回顾——建造者模式
    设计模式回顾——工厂模式
    设计模式回顾——单例模式
    设计模式回顾——设计模式概念与基本原则


    2 什么是模板模式

      模板模式(Template Pattern),指的是定义一个抽象(算法)模板结构父类,具体实现方法由子类实现。模板模式是行为型设计模式中使用较为广泛的设计模式。


    2.1 模板模式组成

      模板模式由抽象类(Abstract Class)、具体子类(Concrete Class)、客户(Client)i三个要素组成。


    • 抽象类(Abstract Class), 声明一个公共抽象模板父类,不变的算法由父类实现,差异部分由子类实现
    • 具体子类(Concrete Class), 继承Abstract Class类,并实现抽象接口和差异部分
    • 客户(Client),客户通过切换不同的子类实现不同的功能,严格来说客户不属于模板模式的一部分

    2.2 模板模式UML图

      根据模板模式的组成要素,以及它们之间的关系,画出模板模式的UML图如下。

    在这里插入图片描述

    模板模式UML图


    2.3 模板模式作用

      子类可以不改变一个模板的结构的情况下,可重新定义模板中的内容或者某些特定步骤。


    3 模板模式优缺点

    优点:

    • 提高代码复用性

      模板模式将类共同部分代码抽象出来放在的父类中,由子类只需实现差异部分,减少子类重复代码。

    • 易扩展

      新增功能时,通过子类实现来拓展,不需改动原有代码和代码框架,符合“开闭原则“。

    • 灵活性好

      所有子类实现的是同一套算法模型,在使用模板的地方,通过切换不同的子类实现不同的功能,符合“里氏替换原则”。

    • 维护性好

      模板模式行为由父类控制,子类实现。


    不足:

    • 降低代码可读性

      模板方式与常规程序设计习惯不同,子类执行的结果影响了父类的结果,会增加代码阅读的难度, 不易理解代码逻辑。

    常规的程序设计习惯,一般是抽象类负责声明最抽象、最一般的事物属性和方法,实现类负责完成具体的事务属性和方法。符合程序员的阅读思维和习惯。

    • 耦合性高

      子类无法影响父类公用模块代码。

    • 增加系统复杂度

      新增不同的功能都需要一个新的子类来实现,导致子类的数目增加,增加了系统实现的复杂度。


    4 什么地方使用模板模式

       模板模式的优点决定了其适用的场景,反过来其缺点即是其不适用的场景。模板模式适用场景:


    • 多个子类具有共同的方法,逻辑、算法等基本相同的场景,可以把共同部分抽象出来

    • 复杂算法分解;不变部分或者核心算法由设计为模板方法,相关细节功能、可变行为由子类实现

    • 需要控制子类扩展场景;模板模式在特定的点调用子类的方法,使得只允许在这些子类上进行扩展。

    • 重构历史遗留代码;利用模板方法重构代码,把共同的代码抽象出来放在父类中,然后通过构造函数约束其行为。


    具体实例:

    • 排序算法,抽象类定义排序接口,子类实现具体数据类型(int、flaot、double、char)的排序

    5 模板模式实现

    实例功能:

      实现一个排序算法,可以对整型、浮点型、字符等各种类型数据进行排序,还可以选择排序类型。


    实例分解:

      将排序算法拆分为几个步骤,共同的、不会改变的用模板方法实现。

    【1】共同的

    • 算法实现框架

    【2】可能会改变的方法

    • 排序数据类型
    • 排序方式
    • 其他拓展

    大体步骤:

    • 抽象父类Sort声明和实现排序算法,这一部分是共同的、不会改变的
    • 子类IntSortFlotaSort分别实现整型数据和单精度浮点型数据排序
    • 子类还可以决定排序方式(升序排序/降序排序),而不影响父类
    • 用户client调用子类实例选择一种排序算法

    实现过程:

    • 第一步,声明抽象模板类Sort
    /* sort.h */
    #ifndef _SORT_H_
    #define _SORT_H_
    
    #include <stdbool.h>
    
    class Sort
    {
    public:
    	virtual ~Sort();
    	virtual void Swap(int)=0;	/* 交互数据 */
    	virtual bool Judge(int)=0;  /* 数据判断方式(排序方式)*/
    	void SortRun();				/* 排序算法框架 */
    protected:
    	Sort();
        int m_Size;
    };
    #endif
    

    • 第二步,抽象类Sort方法实现
    /* sort.cpp */
    #include "sort.h"
    
    Sort::Sort()
    {
    	m_Size = 0;
    }
    
    Sort::~Sort()
    {
    }
    
    void Sort::SortRun()
    {
    	int i = 0,j = 0;
    
    	for (j=0; j<m_Size-1; j++)
    	{
    		for (i=0; i<m_Size-1-j; i++)
    		{
    			if (Judge(i))
    			{
    				Swap(i);
    			}
    		}
    	}
    }
    

    • 第三步,声明整型数据排序子类InstSort,继承抽象父类
    /* int_sort.h */
    #ifndef _INT_SORT_H_
    #define _INT_SORT_H_
    
    #include <stdbool.h>
    #include "sort.h"
    
    class IntSort:public Sort
    {
    public:
    	IntSort();
    	virtual ~IntSort();
    
    	void Swap(int);		/* 重写int型数据交互方法 */
    	bool Judge(int);	/* 重写int型数据判断方法 */
    	void SortData(int*, int);
    private:
    	int *m_pArray;
    };
    #endif
    

    • 第四步,整型数据排序子类InstSort方法实现,实现排序数据类型和排序方式
    /* int_sort.cpp */
    
    #include <iostream>
    #include "int_sort.h"
    
    using namespace std;
    
    IntSort::IntSort()
    {
    }
    
    IntSort::~IntSort()
    {
    }
    
    void IntSort::Swap(int index)
    {
    	int temp;
    	
    	temp = m_pArray[index];
        m_pArray[index] = m_pArray[index+1];
        m_pArray[index+1] = temp;
    }
    
    bool IntSort::Judge(int index)
    {
    	return m_pArray[index] > m_pArray[index+1];	/* 从小到大排序 */
    }
    
    void IntSort::SortData(int *array, int size)
    {
    	this->m_pArray = array;
    	this->m_Size = size;
    	this->SortRun();
    
    	cout<<"int型数据从小到大排序: ";
    	for(int i = 0; i < m_Size; i++)
    	{
    		cout << m_pArray[i] << " ";	
    	}
    	cout<<endl;
    }
    

    • 第五步,声明单精度浮点型数据排序子类FloatSort,继承抽象父类
    /* float_insort.h */
    
    #ifndef _FLOAT_SORT_H_
    #define _FLOAT_SORT_H_
    
    #include <stdbool.h>
    #include "sort.h"
    
    class FloatSort:public Sort
    {
    public:
    	FloatSort();
    	virtual ~FloatSort();
    
    	void Swap(int);		/* 重写float型数据交互方法 */
    	bool Judge(int);	/* 重写float型数据判断方法 */
    	void SortData(float*, int);
    private:
    	float *m_pArray;
    };
    #endif
    

    • 第六步,单精度浮点型数据排序子类FloatSort方法实现,实现排序数据类型和排序方式
    /* float_sort.cpp */
    
    #include <iostream>
    #include "float_sort.h"
    
    using namespace std;
    
    FloatSort::FloatSort()
    {
    }
    
    FloatSort::~FloatSort()
    {
    }
    
    void FloatSort::Swap(int index)
    {
    	float temp;
    	
    	temp = m_pArray[index];
        m_pArray[index] = m_pArray[index+1];
        m_pArray[index+1] = temp;
    }
    
    bool FloatSort::Judge(int index)
    {
    	return m_pArray[index] < m_pArray[index+1];	/* 从大到小排序 */
    }
    
    void FloatSort::SortData(float *array, int size)
    {
    	this->m_pArray = array;
    	this->m_Size = size;
    	this->SortRun();
    
    	cout<<"float型数据从大到小排序: ";
    	for(int i = 0; i < m_Size; i++)
    	{
    		cout << m_pArray[i] << " ";	
    	}
    	cout<<endl;
    }
    

    • 第七步,客户调用不同子类对象实现指定排序功能
    /* client.cpp */
    #include "sort.h"
    #include "int_sort.h"
    #include "float_sort.h"
    
    int main(int argc, char **arv)
    {
    	int intArray[] = {1, 0, 3, 2, 5, 4, 7};
        int size = sizeof intArray / sizeof intArray[0];
        IntSort *intSort = new IntSort;
        intSort->SortData(intArray, size);
    	delete intSort;
    
    	float flaotArray[] = {1.0, 0.3, 1.2, 1.1, 5.4, 2.5, 3.3};
        size = sizeof flaotArray / sizeof flaotArray[0];
        FloatSort *floatSort = new FloatSort;
        floatSort->SortData(flaotArray, size);
    	delete floatSort;
    }
    

    • 最后一步,编写Makefile文件
    VERSION 	=1.00
    CC			=g++
    DEBUG 		=
    CFLAGS		=-Wall
    SOURCES	 	=$(wildcard *.cpp)
    INCLUDES  	=
    LIB_NAMES 	=
    LIB_PATH 	=
    OBJ			=$(patsubst %.cpp, %.o, $(SOURCES))
    TARGET		=client
    
    #links
    $(TARGET):$(OBJ)
    	@mkdir -p output
    	$(CC) $(OBJ) $(LIB_PATH) $(LIB_NAMES) -o output/$(TARGET)$(VERSION)
    	@rm -rf $(OBJ)
    	
    #compile
    %.o: %.c
    	$(CC) $(INCLUDES) $(DEBUG) -c $(CFLAGS) $< -o $@
    
    .PHONY:clean
    clean:
    	@echo "Remove linked and compiled files......"
    	rm -rf $(OBJ) $(TARGET) output 
    

    执行结果:

    acuity@ubuntu:/mnt/hgfs/LSW/STHB/design/template$ make
    g++    -c -o float_sort.o float_sort.cpp
    g++    -c -o int_sort.o int_sort.cpp
    g++    -c -o client.o client.cpp
    g++    -c -o sort.o sort.cpp
    g++  float_sort.o  int_sort.o  client.o  sort.o   -o output/client1.00
    acuity@ubuntu:/mnt/hgfs/LSW/STHB/design/template$ ls
    client.cpp  float_sort.cpp  float_sort.h  int_sort.cpp  int_sort.h  Makefile  Makefile.bak  output  sort.cpp  sort.h
    acuity@ubuntu:/mnt/hgfs/LSW/STHB/design/template$ ./output/client1.00 
    int型数据从小到大排序: 0 1 2 3 4 5 7 
    float型数据从大到小排序: 5.4 3.3 2.5 1.2 1.1 1 0.3 
    

    6 模板模式与策略模式比较

    6.1 差异比较


    相同点:

      两者都是实现算法的灵活使用。


    不同点:

    • 模板模式则重于将算法步骤剥离,共同部分由抽象父类实现,差异部分延迟到子类实现针对是一种算法
    • 策略模式侧重于多个算法可以相互替换,而不影响客户使用针对是多种算法

      例如,对于上述算法实例,模板模式将一种排序算法分解为几个步骤,差异步骤延迟到子类实现,不同类型数据排序、排序类型由子类实现。而对于策略模式,可能会这样考虑,多种排序算法,冒泡排序、选择排序、插入排序等等不同排序算法可以自由切换选择。


    6.2 优缺点和应用场景选择

    优缺点比较:

    模式优点缺点
    模板模式可维护性好,纵向扩展性好耦合性较高,新增功能需增加子类,子类过多增加系统复杂度
    策略模式横向扩展性好,灵活性高客户必须知道所有策略类,策略过增加系统复杂度

    应场景选择

      模板模式和策略模式各有优缺点,关于选择何种模式,是一个重、难点,需根据具体业务功能、功能扩展性、行业特点、自身设计经验等综合考虑来做出选择,可以参考下面的选择。


    场景参考选择模式
    场景针对是一种算法模板模式
    多个类具体共同逻辑、算法,只是一些行为不同模板模式
    行为算法可能会经常变动模板模式
    客户不确定使用的数据类型模板模式
    场景针对是多种算法策略模式
    共同算法和变化算法场景策略模式
    公共行为和变化行为场景策略模式

    展开全文
  • 模板模式准备一个抽象类,将部分逻辑以具体方法以及具体构造形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先制定一个顶级...
  • NULL 博文链接:https://dada-fangfang.iteye.com/blog/1018674
  • 定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构可以定义该算法的某些特定步骤
  • 豆浆制作问题 编写制作豆浆的程序,说明如下: 制作豆浆的流程选材—>添加配料—>浸泡—>放到豆浆机打碎 通过添加不同的配料,可以制作出不同...模板方法模式(Template Method Pattern),又叫模板模式(Te

    豆浆制作问题

    编写制作豆浆的程序,说明如下:

    1. 制作豆浆的流程选材—>添加配料—>浸泡—>放到豆浆机打碎

    2. 通过添加不同的配料,可以制作出不同口味的豆浆

    3. 选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的

    4. 请使用模板方法模式完成(说明:因为模板方法模式,比较简单,很容易就想到这个方案,因此就直接使用,不再使用传统的方案来引出模板方法模式)

    模板方法模式基本介绍

    基本介绍

    1. 模板方法模式(Template Method Pattern),又叫模板模式(Template Pattern),z 在一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。

    2. 简单说,模板方法模式定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤

    3. 这种类型的设计模式属于行为型模式。

    模板方法模式原理类图

    模板方法模式的原理类图

    在这里插入图片描述

    • 对原理类图的说明-即(模板方法模式的角色及职责)
    1. AbstractClass 抽象类, 类中实现了模板方法(template),定义了算法的骨架,具体子类需要去实现其它的抽象方法operationr2,3,4

    2. ConcreteClass 实现抽象方法operationr2,3,4, 以完成算法中特点子类的步骤

    模板方法模式解决豆浆制作问题

    1. 应用实例要求
      编写制作豆浆的程序,说明如下:
      制作豆浆的流程选材—>添加配料—>浸泡—>放到豆浆机打碎
      通过添加不同的配料,可以制作出不同口味的豆浆
      选材、浸泡和放到豆浆机打碎这几个步骤对于制作每种口味的豆浆都是一样的(红豆、花生豆浆。。。)
    2. 思路分析和图解(类图)
      在这里插入图片描述
    3. 代码实现
      客户端
    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();
    	}
    
    }
    

    抽象类

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

    其中一个子类

    public class PeanutSoyaMilk extends SoyaMilk {
    
    	@Override
    	void addCondiments() {
    		// TODO Auto-generated method stub
    		System.out.println(" 第二步加入上好的花生 ");
    	}
    
    }
    

    模板方法模式的钩子方法

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

    2. 还是用上面做豆浆的例子来讲解,比如,我们还希望制作纯豆浆,不添加任何的配料,请使用钩子方法对前面的模板方法进行改造

    3. 代码演示:

    客户端:

    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();
    	}
    
    }
    

    抽象类:里面有勾子方法

    /抽象类,表示豆浆
    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;
    	}
    }
    

    豆浆类(默认不加配料)

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

    什么是钩子函数

    钩子函数这个称呼是很多开发语言中都会涉及到的一个东西,我的理解是系统处理消息时预先设置好的一个函数,就好像某一个周期,这个周期是系统自动执行的,那么这个周期怎样让人为干预他的进程呢,就像是这样。如下图。
    在这里插入图片描述

    总结

    代码执行有一定的流程,比如说第一步做什么,第二步做什么,第三步做什么,每一步对应一个执行函数,这里说的第几步只是说的某些特定阶段,并不一定是连续在一起的。有时候这些函数体可能是空的,什么也没有做,但是是有一个流程在那里的,这种某一步对应的函数就叫钩子函数,并且钩子函数是有一个具体名称的,是系统到了某个阶段检测到有就自动调用,钩子函数里面的代码是有程序员自己编写。并且这个回答是针对所有编程语言说的。

    钩子函数:

    百科:钩子函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。钩子的本质是一段用以处理系统消息的程序,通过系统调用,把它挂入系统。

    emmmm,认认真真读三遍。get关键词,在系统级对所有消息进行过滤,这是什么意思呢?是说钩子函数是在一个事件触发的时候,在系统级捕获到了他,然后做一些操作。一段用以处理系统消息的程序,用以处理系统消息的程序,是说钩子函数是用于处理系统消息的。

    1、是个函数,在系统消息触发时被系统调用

    2、不是用户自己触发的

    3、使用时直接编写函数体

    钩子函数的名称是确定的,当系统消息触发,自动会调用。

    例如react的componentWillUpdate函数,用户只需要编写componentWillUpdate的函数体,当组件状态改变要更新时,系统就会调用componentWillUpdate。

    较常用的钩子函数还有vue生命周期的几个钩子等

    模板方法模式在Spring 框架应用的源码分析

    1. Spring IOC 容器初始化时运用到的模板方法模式
    2. 代码分析+角色分析+说明类图
      在这里插入图片描述
    3. 针对源码的类图(说明层次关系)
      在这里插入图片描述

    模板方法模式的注意事项和细节

    1. 基本思想是:算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改

    2. 实现了最大化代码复用。父类的模板方法和已实现的某些步骤会被子类继承而直接使用。

    3. 既统一了算法,也提供了很大的灵活性。父类的模板方法确保了算法的结构保持不变,同时由子类提供部分步骤的实现。

    4. 该模式的不足之处:每一个不同的实现都需要一个子类实现,导致类的个数增加,使得系统更加庞大

    5. 一般模板方法都加上final 关键字, 防止子类重写模板方法.

    6. 模板方法模式使用场景:当要完成在某个过程该过程要执行一系列步骤这一系列的步骤基本相同,但其个别步骤在实现时可能不同,通常考虑用模板方法模式来处理

    总结

    定义一个一个抽象父类,抽象父类里面有一系列方法(一两个抽象的或者有判断需不要要抽象类的钩子方法)封装成一个方法,子类实现那个抽象方法,
    客户端调用子类

    展开全文
  • NULL 博文链接:https://lfl2011.iteye.com/blog/1693685
  • 设计模式 模板模式和策略模式

    千次阅读 2022-03-19 20:17:12
    模板模式和策略模式,有相识的地方,都是通过对钩子方法的调用,来实现一个业务的完整逻辑。 所以这里我将两种模式放在一起介绍,比较容易加深对这两种模式的理解。 模板模式模板模式(Template Pattern)中,一...
  • spring模板方法模式.zip,spring模板方法模式,JdbcTemplateUserImpl.java,TemplatePatternImpl2.java,TemplatePattern.java,JdbcTemplate.java,spring模板方法.txt,TemplatePatternImpl.java
  • Java中常用的设计模式【模板模式

    千次阅读 2022-02-26 15:27:50
    模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。 优点 封装不变部分,...
  • Java设计模式-模板模式

    千次阅读 多人点赞 2021-08-05 11:19:49
    Java设计模式-模板模式 什么是模板模式模板模式,顾名思义,就是通过模板拓印的方式。 定义模板,就是定义框架、结构、原型。定义一个我们共同遵守的约定。 定义模板,我们的剩余工作就是对其进行充实、丰润,...
  • 模板模式定义模板模式,在Gof的《设计模式》中定义为:Define the skeleton of an algorithm in an operation,
  • java策略模式+工厂模式+模板模式

    千次阅读 2022-02-12 18:08:42
    java策略模式+工厂模式+模板模式
  • 策略模式和模板模式有一个最重要的区别,即模板模式一般只针对一套算法,注重对同一个算法的不同细节进行抽象提供不同的实现。而策略模式注重多套算法多套实现,在算法中间不应该有交集,因此算法和算法只间一般不会...
  • 复用和扩展是模板模式的两大作用,实际上,还有另外一个技术概念,也能起到跟模板模式相同的作用,那就是回调(Callback)。A 类事先注册某个函数 F 到 B类
  • java模式--模板模式实例代码,请参考我的博客:http://blog.csdn.net/yayun0516
  • 设计模式之模板模式和工厂模式

    千次阅读 2019-06-15 16:02:49
    模板模式和工厂模式的类别分类为“交给子类”,即两种设计模式都是通过子类来实现具体的功能。主角是子类,而不像上次的适应设计模式,主角是连接器。这种差别着重体现在我们在工业设计中对需求的不同理解和实现。 ...
  • 本文内容包括:引言修改现有服务应用恰当的模式WS响应模板模式应用WS响应模板模式我们实现的结果结束语下载参考资料本系列文章探索可重用资产、菜谱和软件模式,并说明它们可以如何促进SOA解决方案的开发。...
  • 【C++】CRTP:奇异递归模板模式

    千次阅读 2022-02-26 09:22:39
    CRTP的全称是Curiously Recurring Template Pattern,即奇异递归模板模式,简称CRTP。CRTP是一种特殊的模板技术和使用方式,是C++模板编程中的一种惯用法。CRTP的特性表现为: 基类是一个模板类 派生类继承该基类...
  • 【设计模式】模板模式——jdbc案例

    千次阅读 2020-09-16 21:19:34
    假如开一把lol,必须要做哪些事呢?...就是模板模式了大概的样子,在模板模式中,一个抽象类公开定义了执行它的方法的方式模板,它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行
  • 模板模式Template Pattern

    2019-03-09 16:59:44
    模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
  • 第十六章:模板方法模式一、豆浆制作问题编写制作豆浆的程序,说明如下:制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎通过添加不同的配料,可

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 520,375
精华内容 208,150
关键字:

模板模式

友情链接: QDSKtiaozhi.rar