设计模式

模板模式

定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的某些特定步骤。

简单示例

//抽象类(基类)
class AbstractClass
{
public:
	//模板方法,定义一个算法的框架流程
	void templateMethod(){
		//do something
		method1();
		method2();
		method3();
	}

protected://声明为protected重要
	//公共方法
	void method1(){
		//do something
	}
	//子类必须实现的方法
	virtual void method2()=0;
	//默认实现
	virtual void method3(){
		//do something
	}
};

//具体类(派生类)
class ConcreteClass:public AbstractClass
{
protected://注意声明为protected
	//实现方法2
	void method2(){
		//do something
	}
	//重定义方法3
	void method3(){
		//do something
	}
};

场景示例

#include <iostream>

using namespace std;

//基类
class FingerprintModule
{
public:
	FingerprintModule() {}
	virtual ~FingerprintModule() {}
	
	void algorithm()
	{
		//1.采图
		getImage();
		//2.安全模式下加密和解密
		if (isSafeMode())
		{
			//2.1.加密
			encrypt();
			//2.2.解密
			decrypt();
		}
		//3.处理Image
		processImage();
		//4.处理结果
		output();
	}

protected:
	void getImage()
	{
		printf("采指纹图像\n");
	}
	void output()
	{
		printf("指纹图像处理完成!\n");
	}
	virtual bool isSafeMode() = 0;
	virtual void processImage() = 0;

	//加解密
	virtual void encrypt() = 0;
	virtual void decrypt() = 0;

};

//派生类
class FingerprintModuleA :public FingerprintModule
{
public:
	FingerprintModuleA() {}
	virtual ~FingerprintModuleA() {}
protected:
	void processImage() 
	{
		printf("使用 第一代版本算法 处理指纹图像\n");
	}
	bool isSafeMode() 
	{
		printf("安全模式\n");
		return true;
	}
	void encrypt()
	{
		printf("使用RSA密钥加密\n");
	}
	void decrypt()
	{
		printf("使用RSA密钥解密\n");
	}
};


// 派生类
class FingerprintModuleB :public FingerprintModule
{
public:
	FingerprintModuleB() {}
	virtual ~FingerprintModuleB() {}
protected:
	void processImage() 
	{
		printf("使用 第二代版本算法 处理指纹图像\n");
	}
	bool isSafeMode()
	{
		printf("非安全模式\n");
		return false;
	}
	void encrypt() {}
	void decrypt() {}
};

// 派生类
class FingerprintModuleC :public FingerprintModule
{
public:
	FingerprintModuleC() {}
	virtual ~FingerprintModuleC() {}
protected:
	void processImage() 
	{
		printf("使用 第一代版本算法 处理指纹图像\n");
	}
	bool isSafeMode() 
	{
		printf("安全模式\n");
		return true;
	}
	void encrypt()
	{
		printf("使用DH密钥加密\n");
	}
	void decrypt()
	{
		printf("使用DH密钥解密\n");
	}
};

void main()
{
	FingerprintModule *fpA = new FingerprintModuleA();
	fpA->algorithm();
	printf("\n");
	FingerprintModule *fpB = new FingerprintModuleB();
	fpB->algorithm();
	printf("\n");
	FingerprintModule *fpC = new FingerprintModuleC();
	fpC->algorithm();
	printf("\n");
	if (fpA) delete fpA;
	if (fpB) delete fpB;
	if (fpC) delete fpC;
}

策略模式

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。

简单示例

#include <iostream>
using namespace std;

//the abstract strategy
class Strategy
{
public:
	Strategy() {}
	virtual ~Strategy() {}
	//定义为public的方法
	virtual void AlgorithmInterface() = 0;
};

class ConcreteStrategyA :public Strategy
{
public :
	ConcreteStrategyA() {}
	virtual ~ConcreteStrategyA(){}
	void AlgorithmInterface()
	{
		cout << "I am from ConcreteStrategyA." << endl;
	}
};

class ConcreteStrategyB :public Strategy
{
public:
	ConcreteStrategyB() {}
	virtual ~ConcreteStrategyB() {}
	void AlgorithmInterface()
	{
		cout << "I am from ConcreteStrategyB." << endl;
	}
};

class ConcreteStrategyC :public Strategy
{
public:
	ConcreteStrategyC() {}
	virtual ~ConcreteStrategyC() {}
	void AlgorithmInterface()
	{
		cout << "I am from ConcreteStrategyC." << endl;
	}
};

class Context
{
public:
	Context(Strategy *pStrategyArg) :pStrategy(pStrategyArg)
	{}
	virtual ~Context() {}
	void ContextInterface()
	{
		pStrategy->AlgorithmInterface();
	}
private:
	Strategy *pStrategy;
};

void main()
{
	Strategy *pStrategyA = new ConcreteStrategyA;
	Strategy *pStrategyB = new ConcreteStrategyB;
	Strategy *pStrategyC = new ConcreteStrategyC;
	Context *pContextA = new Context(pStrategyA);
	Context *pContextB = new Context(pStrategyB);
	Context *pContextC = new Context(pStrategyC);
	pContextA->ContextInterface();
	pContextB->ContextInterface();
	pContextC->ContextInterface();

	if (pContextA) delete pContextA;
	if (pContextB) delete pContextB;
	if (pContextC) delete pContextC;
	if (pStrategyA) delete pStrategyA;
	if (pStrategyB) delete pStrategyB;
	if (pStrategyC) delete pStrategyC;
}

策略模式和简单工厂模式相结合

#include <iostream>
using namespace std;

//Define the strategy type
typedef enum StrategyType
{
	StrategyA,
	StrategyB,
	StrategyC
}STRATEGYTYPE;

//the abstract strategy
class Strategy
{
public:
	Strategy() {}
	virtual ~Strategy() {}
	//定义为public的方法
	virtual void AlgorithmInterface() = 0;
};

class ConcreteStrategyA :public Strategy
{
public :
	ConcreteStrategyA() {}
	virtual ~ConcreteStrategyA(){}
	void AlgorithmInterface()
	{
		cout << "I am from ConcreteStrategyA." << endl;
	}
};

class ConcreteStrategyB :public Strategy
{
public:
	ConcreteStrategyB() {}
	virtual ~ConcreteStrategyB() {}
	void AlgorithmInterface()
	{
		cout << "I am from ConcreteStrategyB." << endl;
	}
};

class ConcreteStrategyC :public Strategy
{
public:
	ConcreteStrategyC() {}
	virtual ~ConcreteStrategyC() {}
	void AlgorithmInterface()
	{
		cout << "I am from ConcreteStrategyC." << endl;
	}
};

class Context
{
public:
	Context(STRATEGYTYPE strategyType)
	{
		switch (strategyType)
		{
		case StrategyA:
			pStrategy = new ConcreteStrategyA;
			break;
		case StrategyB:
			pStrategy = new ConcreteStrategyB;
			break;
		case StrategyC:
			pStrategy = new ConcreteStrategyC;
			break;
		default:
			break;
		}
	}
	virtual ~Context() 
	{
		if (pStrategy)
		{
			delete pStrategy;
		}
	}
	void ContextInterface()
	{
		if (pStrategy)
			pStrategy->AlgorithmInterface();
	}
private:
	Strategy *pStrategy;
};

void main()
{
	Context *pContext = new Context(StrategyB);
	pContext->ContextInterface();
	if (pContext)delete pContext;
}

场景示例

#include <iostream>

using namespace std;

//Define the strategy type
typedef enum StrategyType
{
	StrategyA,
	StrategyB,
	StrategyC
}STRATEGYTYPE;

//the abstract strategy
class Strategy
{
public:
	Strategy() {}
	virtual ~Strategy() {}
	//定义为public的方法
	virtual void sort(int arr[],int N) = 0;
};

//具体策略类:冒泡排序
class BubbleSort :public Strategy
{
public :
	BubbleSort() 
	{
		printf("冒泡排序\n");
	}
	virtual ~BubbleSort(){}
	void sort(int arr[],int N)
	{
		for (int i = 0;i < N;++i)
		{
			for (int j = 0;j < N - i - 1;++j)
			{
				if (arr[j] > arr[j + 1])
				{
					int tmp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = tmp;
				}
			}
		}
	}
};

//具体策略类:选择排序
class SelectionSort :public Strategy
{
public:
	SelectionSort()
	{
		printf("选择排序\n");
	}
	virtual ~SelectionSort() {}
	void sort(int arr[],int N)
	{
		int i, j, k;
		for (i = 0;i < N;++i)
		{
			k = i;
			for (j = i + 1;j < N;++j)
			{
				if (arr[j] < arr[k])
				{
					k = j;
				}
			}
			int temp = arr[i];
			arr[i] = arr[k];
			arr[k] = temp;
		}
	}
};

//具体策略类:插入排序
class InsertSort :public Strategy
{
public:
	InsertSort() 
	{
		printf("插入排序\n");
	}
	virtual ~InsertSort() {}
	void sort(int arr[],int N)
	{
		int i, j;
		for (i = 1;i < N;++i)
		{
			int tmp = arr[i];
			for (j = i - 1;j >= 0;--j)
			{
				if (tmp < arr[j])
				{
					arr[j + 1] = arr[j];
				}
				else
				{
					break;
				}
			}
			arr[j + 1] = tmp;
		}

	}
};


//上下文类
class Context
{
public:
	Context()
	{
		arr = NULL;
		N = 0;
	}
	Context(int iArr[], int iN)
	{
		this->arr = iArr;
		this->N = iN;
	}
	virtual ~Context() 
	{
	}

	void setSortStrategy(Strategy *iSortStrategy)
	{
		this->sortStrategy = iSortStrategy;
	}

	void sort()
	{
		this->sortStrategy->sort(arr, N);
		printf("输出: ");
		this->print();
	}
	void setInput(int iArr[], int iN)
	{
		this->arr = iArr;
		this->N = iN;
	}
	void print()
	{
		for (int i = 0;i < N;++i)
		{
			printf("%4d", arr[i]);
		}
		printf("\n");
	}
private:
	Strategy *sortStrategy;
	int *arr;
	int N;
};

void main()
{
	Context *ctx = new Context();
	int arr[] = { 10,23,-1,0,300,87,28,77,-32,2 };
	ctx->setInput(arr, sizeof(arr) / sizeof(int));
	printf("输入:");
	ctx->print();

	//冒泡排序
	ctx->setSortStrategy(new BubbleSort());
	ctx->sort();

	//选择排序
	ctx->setSortStrategy(new SelectionSort());
	ctx->sort();

	//插入排序
	ctx->setSortStrategy(new InsertSort());
	ctx->sort();

	printf("\n\n");
}

模板方法模式和策略模式之间的区别

两者的主要区别在于具体算法的选择:
  通过模板方法模式,这通过子类化模板在编译时发生。每个子类通过实现模板的抽象方法提供了不同的具体算法。当客户端调用模板外部接口的方法时,模板根据需要调用其抽象方法(其内部接口)来调用算法。
  相比之下,策略模式允许在运行时通过遏制来选择算法。具体的算法是通过单独的类或函数来实现的,这些类或函数作为其构造函数或设置方法的参数传递给策略。该参数选择哪种算法可以根据程序的状态或输入动态变化。

综上所述:

  • 模板方法模式:通过子类化来编译时间算法选择
  • 策略模式:通过遏制运行时算法选择

以下摘自策略模式和模版模式的异同
Strategy模式的应用场景是:

  1. 多个类的分别只是在于行为不同
  2. 你需要对行为的算法做很多变动
  3. 客户不知道算法要使用的数据

Template Method模式的应用场景是:

  1. 你想将相同的算法放在一个类中,将算法变化的部分放在子类中实现
  2. 子类公共的算法应该放在一个公共的类中,避免代码重复

  我们知道,设计模式中有这么一个原则:Prefer composition to inheritance,这句话的背景是OO初期大家都把继承看作是万能的,并过度使用继承来实现多态->可扩展。
  理解原则的时候不能脱离它的背景,不然就成盲从了.Template Method模式应该是伴随着OO的出现而萌生的。它是OO中最直观的思考方式的结果,基类留下可变化的空间给子类,由继承类来决定具体行为。听起来是不错,不过…一旦基类的接口发生了变化,每个继承类都得跟着修改才能够继续使用。这就是所谓高耦合与难维护的说法的来源。
  Strategy与Template Method模式算是composition与inheritance的典型应用了。
  GoF的设计模式那本书里有这么一句话:“Template methods use inheritance to vary part of an algorithm. Strategies use delegation to vary the entire algorithm.”,说的正是这个问题。回到具体问题上,如果我们要封装的算法适合于提供给用户任意使用,是"一整个算法",那么用Strategy模式较好;如果要封装的变化是一个算法中的部分(换言之,大算法的步骤是固定的),而且我们不希望用户直接使用这些方法,那么应该使用Templa Method模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值