策略模式的定義:ios
策略模式是指定義一系列的算法,把它們一個個封裝起來,而且使它們可相互替換。本模式使得算法可獨立於使用它的客戶而變化。算法
優勢: 一、算法能夠自由切換。 二、避免使用多重條件判斷。 三、擴展性良好。編程
缺點: 一、策略類會增多。 二、全部策略類都須要對外暴露。設計模式
類圖以下:函數
Strategy: 抽象策略類,定義抽象的函數算法讓繼承的子類實現。spa
ConcreteStrategy:封裝了繼續相關的算法和行爲,即函數的具體功能的實現。設計
Context:持有一個策略類的引用,最終給客戶端調用。指針
我認爲策略模式的重點在於context類的定義,這也是策略模式與模板模式最大的不一樣,即經過對策略基類Strategy的組合出的類context,根據子類的不一樣,靈活地經過類context中的多態指針調用來實現一系列子類算法,也叫根據不一樣策略執行不一樣的行爲。策略由外部環境決定。code
總結起來就是Context 指向 Strategy (由指針實現);Context 經過 Strategy 接口,調用一系列算法;ConcreteStrategy 實現了一系列具體的算法。blog
下面舉一個例子來講明策略模式的好處:
假如一個跨國公司A在多個國家有分公司,且在不一樣國家的經營模式根據國家國情會有所不一樣,並且分公司負責人也不一樣,要求編寫程序實現這一狀況的描述。首先容易想到的是定義一個基類,而後針對不一樣的分公司用switch語句進行選擇來編寫。代碼以下:
1
#include <iostream>
using namespace std;
class Company
{
private:
string name;
int type;
public:
Company(string n,int t)
{
name=n;
type=t;
}
void printcompany()
{
switch(type)
{
case 1:
cout<<"負責人"<<name<<endl;
China();
break;
case 2:
cout<<"負責人"<<name<<endl;
America();
break;
case 3:
cout<<"負責人"<<name<<endl;
France();
break;
}
}
void China()
{
cout<<"中國分公司:經營模式1的具體實現..."<<endl;
}
void America()
{
cout<<"美國分公司:經營模式2的具體實現..."<<endl;
}
void France()
{
cout<<"法國分公司:經營模式3的實現..."<<endl;
}
};
int main()
{
Company a1("張三",1);
Company a2("李四",2);
Company a3("王五",3);
a1.printcompany();
cout<<"================================================="<<endl;
a2.printcompany();
cout<<"================================================="<<endl;
a3.printcompany();
}
然而這個程序只是最簡單的作法,其擴展性並很差,例如要在印度一個新分公司,須要在類添加相關公司經營模式函數,也要在switch添加相關公司內容,若是某個分公司的經營模式要改變,也要經過去類中尋找相應的函數去修改,但若是分公司多了,類就會變得很臃腫且不方便查找修改。若是咱們採用策略模式,把函數定義寫在抽象基類中,把每一個分公司寫成一個繼承子類,由不一樣的算法實現不一樣經營模式,而後再寫一個封裝的context類來實現客戶端調用,這樣就能夠一目瞭然了,創建分公司和修改信息就只須要對子類進行操做,基類並不須要任何修改,並且經過contex類提供的接口能夠很方便的選擇展現不一樣公司的狀況,代碼以下:
#include <iostream> using namespace std; class Company { public: string name; virtual void Management()=0; }; class Company1:public Company { public: Company1(string n) {
name=n; } void printcompany() { cout<<"負責人"<<name<<endl; } virtual void Management() { cout<<"中國分公司:經營模式1的具體實現..."<<endl; } }; class Company2:public Company { public: Company2(string n) { name=n; } void printcompany() { cout<<"負責人"<<name<<endl; } virtual void Management() { cout<<"美國分公司:經營模式2的具體實現..."<<endl; } }; class Company3:public Company { public: Company3(string n) { name=n; } void printcompany() { cout<<"負責人"<<name<<endl; } virtual void Management() { cout<<"法國分公司:經營模式3的實現..."<<endl; } }; class Context { public: Company *com; Context(Company *c) { com=c; } void printcompany() { com->Management(); } }; int main() { Company *china=new Company1("張三"); Company *america=new Company2("張三"); Company *france=new Company3("張三"); Context a1(china); Context a2(america); Context a3(france); a1.printcompany(); cout<<"================================================="<<endl; a2.printcompany(); cout<<"================================================="<<endl; a3.printcompany(); }
從設計模式的角度來講,這種模式隔離變化,編程到接口,有新公司加入,只要寫一個子類就能夠,不須要改變其餘類的代碼,因此其餘的類都是穩定的,這就體現了咱們策略模式的設計原則和目的。