设计模式笔记11:模板方法设计模式(Template Method Pattern)

一、模板方法模式的内容

模板模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。模板方法是一种类行为型模式。

模板方法模式是基于继承的代码复用基本技术,模板方法模式的结构和用法也是面向对象设计的核心之一。在模板方法模式中,可以将相同的代码放在父类中,而将不同的方法实现放在不同的子类中。

在模板方法模式中,我们需要准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来让子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式的用意。模板方法模式体现了面向对象的诸多重要思想,是一种使用频率较高的模式。

二、模版方法模式的结构

模版方法模式的静态结构如下图所示。


这里涉及到两个角色:

  • 抽象模版(AbstractClass)角色有如下的责任:

定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。

定义并实现了一个模版方法。这个模版方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。

  • 具体模版(ConcreteClass)角色有如下的责任:

实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。

每一个抽象模版角色都可以有任意多个具体模版角色与之对应,而每一个具体模版角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。

三、模板方法模式分析

  • 模板方法模式是一种类的行为型模式,在它的结构图中只有类之间的继承关系,没有对象关联关系。
  • 在模板方法模式的使用过程中,要求开发抽象类和开发具体子类的设计师之间进行协作。一个设计师负责给出一个算法的轮廓和骨架,另一些设计师则负责给出这个算法的各个逻辑步骤。实现这些具体逻辑步骤的方法称为基本方法(Primitive Method),而将这些基本法方法汇总起来的方法称为模板方法(Template Method),模板方法模式的名字从此而来。
  • 模板方法:一个模板方法是定义在抽象类中的、把基本操作方法组合在一起形成一个总算法或一个总行为的方法。
  • 基本方法:基本方法是实现算法各个步骤的方法,是模板方法的组成部分。
  1. 抽象方法(Abstract Method)
  2. 具体方法(Concrete Method)
  3. 钩子方法(Hook Method):“挂钩”方法和空方法
  • 在模板方法模式中,由于面向对象的多态性,子类对象在运行时将覆盖父类对象,子类中定义的方法也将覆盖父类中定义的方法,因此程序在运行时,具体子类的基本方法将覆盖父类中定义的基本方法,子类的钩子方法也将覆盖父类的钩子方法,从而可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。
  • 为了防止改变模板方法中的算法,可以将模板方法声明为final。
  • 策略模式和模板方法模式都封装了算法,一个用了组合,一个用了继承。策略模式定义了算法头,客户可以轻易的使用不同的算法,而模板方法模式定义了算法的大纲,由其子类定义某些步骤的内容,算法的结构是无法改变的。
  • 工厂方法是模板方法的一种特殊变体。

四、模板方法设计模式示例代码

public abstract class HookDemo
{
	public abstract void getData();
	
    public void convertData()
	{
		System.out.println("通用的数据转换操作。");
	}
	
	public abstract void displayData();

    public void process()
    {
        getData();
        if(isValid())
        {
            convertData();	
        }
   	    displayData();
    }
    
    public boolean isValid()
    {
    	return true;
    }
} 

class SubHookDemo extends HookDemo
{
	public void getData()
	{
		System.out.println("从XML配置文件中获取数据。");
	}
	
	public void displayData()
	{
		System.out.println("以柱状图显示数据。");
	}
	
	public boolean isValid()
    {
    	return false;
    }	
}

class Client
{
	public static void main(String a[])
	{
		HookDemo hd;
		
		hd=new SubHookDemo();
		hd.process();
	}
}

abstract class DBOperator
{
	public abstract void connDB();
    public void openDB()
	{
		System.out.println("打开数据库");
	}
	public void useDB()
	{
		System.out.println("使用数据库");
	}
	public void closeDB()
	{
		System.out.println("关闭数据库");	
	}
   public void process()
   {
    connDB();
   	openDB();
   	useDB();
   	closeDB();
   }
} 

class DBOperatorSubA extends DBOperator
{
	public void connDB()
	{
		System.out.println("使用JDBC-ODBC桥接连接数据库");		
	}
}

class DBOperatorSubB extends DBOperator
{
	public void connDB()
	{
		System.out.println("使用连接池连接数据库");		
	}
}

class Client
{
	public static void main(String a[])
	{
		DBOperator db1;
		
		db1=new DBOperatorSubA();
		db1.process();
		System.out.println("---------------------------------------");			
		db1=new DBOperatorSubB();
		db1.process();
	}
}

五、模式扩展

关于继承的讨论
  • 模板方法模式鼓励我们恰当使用继承,此模式可以用来改写一些拥有相同功能的相关类,将可复用的一般性的行为代码移到父类里面,而将特殊化的行为代码移到子类里面。这也进一步说明,虽然继承复用存在一些问题,但是在某些情况下还是可以给开发人员带来方便,模板方法模式就是体现继承优势的模式之一。
好莱坞原则
  • 在模板方法模式中,子类不显式调用父类的方法,而是通过覆盖父类的方法来实现某些具体的业务逻辑,父类控制对子类的调用,这种机制被称为好莱坞原则(Hollywood Principle),好莱坞原则的定义为:“不要给我们打电话,我们会给你打电话(Don‘t call us, we’ll call you)”。
  • 在模板方法模式中,好莱坞原则体现在:子类不需要调用父类,而通过父类来调用子类,将某些步骤的实现写在子类中,由父类来控制整个过程。
  • 好莱坞原则告诉我们,将决策权放在最高层模块中,以便决定如何以及何时调用底层模块。
钩子方法的使用
  • 钩子方法的引入使得子类可以控制父类的行为。
  • 最简单的钩子方法就是空方法,也可以在钩子方法中定义一个默认的实现,如果子类不覆盖钩子方法,则执行父类的默认实现代码。
  • 比较复杂一点的钩子方法可以对其他方法进行约束,这种钩子方法通常返回一个boolean类型,即返回true或false,用来判断是否执行某一个基本方法。

六、模板方法模式优缺点

模板方法模式的优点
  • 模板方法模式在一个类中形式化地定义算法,而由它的子类实现细节的处理。
  • 模板方法模式是一种代码复用的基本技术。
  • 模板方法模式导致一种反向的控制结构,通过一个父类调用其子类的操作,通过对子类的扩展增加新的行为,符合“开闭原则”。

模板方法模式的缺点
  • 每个不同的实现都需要定义一个子类,这会导致类的个数增加,系统更加庞大,设计也更加抽象,但是更加符合“单一职责原则”,使得类的内聚性得以提高。

七、模板方法模式适用环境

在以下情况下可以使用模板方法模式:
  1. 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
  2. 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。
  3. 对一些复杂的算法进行分割,将其算法中固定不变的部分设计为模板方法和父类具体方法,而一些可以改变的细节由其子类来实现。
  4. 控制子类的扩展。

八、模板方法模式应用

(1) 模板方法模式广泛应用于框架设计(如Spring,Struts等)中,以确保父类控制处理流程的逻辑顺序(如框架的初始化)。

(2) Java单元测试工具JUnit中的TestCase类的设计:

public void runBare() throws Throwable {
 setUp();
 try {
  runTest();
 }
 finally {
  tearDown();
 }
}

Template method(recognizeable by behavioral methods which already have a "default" behaviour definied by an abstract type)

九、参考资料

EPLAN P8.2.7破解教程 心酸路程呀!!! 1、打开“Electric P8 2.7.”目录,运行“setup.exe”开始安装,选择系统和程序。 2、接受许可协议 3、进行用户设置 4、自定义安装功能,等待安装完成 5、安装完毕后,解压打开安装包“Patch EPLAN P8 (V1.8-V2.7)”文件夹,以管理员身份运行 HASPUserSetup.exe。 6、然后运行“EPLAN 2.1-27 X64 crack.exe”,弹出窗口选择安装驱动 7、打开计算机设备管理(方法右键我的电脑,选择管理)然后如下图操作,添加过时硬件。 8、选择安装我手动从列表选择的硬件,下一步 显示所有设备,下一步 从磁盘安装 ,浏览选择附件上的驱动文件(MultiKey64里面的multikey.inf),然后确定。 如果显示multikey无法使用等感叹号,需要再下载更新软件,比如用驱动精灵更新usb_key 程序,我的电脑更新的程序是hasp_srm_drv_550_64_11.exe 9、下一步安装,就成功了,如果弹出没有数字认证的提示,直接同意就可以了。至此,虚拟狗驱动就完成了。打开Eplan,按照下图选择,然后试一下,就可以进入eplan界面了。 对于P8.2.7版本,解决卡顿的补丁安装方法比较简单。 在EPLAN P8 2.7破解教程.rar压缩包里面,将破解补丁“version.dll”复制到安装目录下,默认目录为C:Program FilesEPLANPlatform2.7.3Bin(我把程序装到了D盘之中),然后重启Eplan即可。 用管理员权限打开PYG_DLL_Patcher_x64.exe 如果打开语言是英文,可以用txt(记事本)打开修改PYG_Dll_Patcher_x64.ini修改为“CurrentLanguage=2” 不要勾选两个有关patch…… 点击“load”(加载)加载对应版本,不如2.7版本的…… 然后点击“build” 点击 “OK” version.dll 文件已经自动输出在 “…version.dll Creator\EPLAN”文件夹里面 如果打开之后无模板无法新建,网上说可以在c盘搜索,比如搜索FL_1219-2_tpl001.ept等,我没能找到,我的解决方法是打开eplan>帮助>EPLAN download manager> 选择更新如下黄色的模块就可以有模板了。 如果出现无法打开数据库ESS_part001.mdb 那就打开C盘或者安装盘搜索 *.Mdb,搜索到关于eplan目录下的文件 比如在C:\ProgramData\EPLAN\O_Data\Platform Data\2.7.3\Translation\EPLAN copy到C:\Users\Public\EPLAN\Data\部件\Microsoft目录下 如果出现无法打开功能定义库 在c盘搜索fctdeflib,然后打开所在文件夹,复制该文件里面所有文件,然后找到FctDefLib.fdb 文件夹,把里面的文件都复制到C:\Users\Public\EPLAN\Data\功能定义 如果没有“功能定义”文件夹,就自己创建一个然后把文件复制进去。 复制完之后打开eplan软件 打开选项>设置 选择功能定义,把刚刚新建的文件《功能定义》的路径选择进去。 到此为止。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值