设计模式

it2023-10-29  76

模板模式

定义一个操作中的算法的骨架(稳定),而将一些步骤延迟(变化)到子类中。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模式的应用场景是:

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

Template Method模式的应用场景是:

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

  我们知道,设计模式中有这么一个原则: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)