23种设计模式——模板方法模式组件协作

Posted J-A

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了23种设计模式——模板方法模式组件协作相关的知识,希望对你有一定的参考价值。

文章目录

亦称: Template Method

意图

它的主要思想是,定义一个操作的一系列步骤,对于某些暂时确定不下来的步骤,就留给子类去实现好了,这样不同的子类就可以定义出不同的步骤。因此,模板方法的核心在于定义一个“骨架”。模板方法模式很好的体现了好莱坞原则(Hollywood Principle): Don’t call us, we’ll call you。使得父类来控制程序流程,父类根据程序执行需要将子类的功能勾到父类中,程序流程倒置这个点需要花一点时间适应。

什么时候使用模板方法

  1. 算法的整体步骤很固定,但是其中一些方法需要根据场景不同,进行不同的实现,我们就可以将易变的抽象出来,交由子类实现。
  2. 当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。
  3. 当需要控制子类的扩展部分是否执行时,可以在特定的方法前调用钩子操作,这样就增强了模板方法的灵活性。

真实世界类比

可对典型的建筑方案进行微调以更好地满足客户需求。

模板方法可用于建造大量房屋。 标准房屋建造方案中可提供几个扩展点, 允许潜在房屋业主调整成品房屋的部分细节。

每个建造步骤 (例如打地基、 建造框架、 建造墙壁和安装水电管线等) 都能进行微调, 这使得成品房屋会略有不同。

常说的钩子

钩子 相信大家曾经有听到过,但是可能一直不太理解,它是一种被声明在抽象类中的方法,但只有空的或者默认的实现。 钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩由子类自行决定。

它和模板方法是搭配着使用的,假设现在要加入一个新的方法调用,改变了模板方法。但是这个方法又不是所有的子类都需要实现,希望将这个选择的能力交给子类选择,就可以将这个方法在超类中定义为空方法或者默认实现,子类可以选择覆盖,但不一定非要这么做,这就是钩子的作用。

模板方法的实现

1、抽象类 (Abstract­Class) 会声明作为算法步骤的方法, 以及依次调用它们的实际模板方法。 算法步骤可以被声明为 抽象类型, 也可以提供一些默认实现。

2、具体类 (Concrete­Class) 可以重写所有步骤, 但不能重写模板方法自身。

class AbstractClass 

	/**
	 * The template method defines the skeleton of an algorithm.
	 */
public:
	void TemplateMethod() const 
		this->BaseOperation1();
		this->RequiredOperations1();
		this->BaseOperation2();
		this->Hook1();
		this->RequiredOperation2();
		this->BaseOperation3();
		this->Hook2();
	
	/**
	 * These operations already have implementations.
	 */
protected:
	void BaseOperation1() const 
		std::cout << "AbstractClass says: I am doing the bulk of the work\\n";
	
	void BaseOperation2() const 
		std::cout << "AbstractClass says: But I let subclasses override some operations\\n";
	
	void BaseOperation3() const 
		std::cout << "AbstractClass says: But I am doing the bulk of the work anyway\\n";
	
	/**
	 * These operations have to be implemented in subclasses.
	 */
	virtual void RequiredOperations1() const = 0;
	virtual void RequiredOperation2() const = 0;
	/**
	 * These are "hooks." Subclasses may override them, but it's not mandatory
	 * since the hooks already have default (but empty) implementation. Hooks
	 * provide additional extension points in some crucial places of the
	 * algorithm.
	 */
	virtual void Hook1() const 
	virtual void Hook2() const 
;
/**
 * Concrete classes have to implement all abstract operations of the base class.
 * They can also override some operations with a default implementation.
 */
class ConcreteClass1 : public AbstractClass 

protected:
	void RequiredOperations1() const override 
		std::cout << "ConcreteClass1 says: Implemented Operation1\\n";
	
	void RequiredOperation2() const override 
		std::cout << "ConcreteClass1 says: Implemented Operation2\\n";
	
;
/**
 * Usually, concrete classes override only a fraction of base class' operations.
 */
class ConcreteClass2 : public AbstractClass 

protected:
	void RequiredOperations1() const override 
		std::cout << "ConcreteClass2 says: Implemented Operation1\\n";
	
	void RequiredOperation2() const override 
		std::cout << "ConcreteClass2 says: Implemented Operation2\\n";
	
	void Hook1() const override 
		std::cout << "ConcreteClass2 says: Overridden Hook1\\n";
	
;

模板方法模式的优缺点

优点缺点
很好的符合的“开闭原则”部分客户端可能会受到算法框架的限制
提高了代码的复用度通过子类抑制默认步骤实现可能会导致违反_里氏替换原则
模板方法中的步骤越多, 其维护工作就可能会越困难

以上是关于23种设计模式——模板方法模式组件协作的主要内容,如果未能解决你的问题,请参考以下文章

23种设计模式——观察者模式组件协作

23种设计模式之模板方法(Template Method)

23种设计模式之模板方法模式

23种设计模式之模板方法模式

23种设计模式—— 模板方法

23种设计模式—— 模板方法