設計模式分爲三種類型
創建型模式:單例模式、抽象工廠模式、建造者模式、工廠模式、原型模式。
結構型模式:適配器模式、橋接模式、裝飾模式、組合模式、外觀模式、享元模式、代理模式。
行爲型模式:模版方法模式、命令模式、迭代器模式、觀察者模式、中介者模式、備忘錄模式、解釋器模式、狀態模式、策略模式、職責鏈模式、訪問者模式。
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
設計原則
面向對象有幾個原則:開閉原則(Open Closed Principle,OCP)
里氏代換原則(Liskov Substitution Principle,LSP)
依賴倒轉原則(Dependency Inversion Principle,DIP)
接口隔離原則(Interface Segregation Principle,ISP)
合成/聚合複用原則(Composite/Aggregate Reuse Principle,CARP)
最小知識原則(Principle of Least Knowledge,PLK,也叫迪米特法則)
開閉原則具有理想主義的色彩,它是面向對象設計的終極目標。其他幾條,則可以看做是開閉原則的實現方法。設計模式就是實現了這些原則,從而達到了代碼複用、增加可維護性的目的。
簡單工廠模式
主要用於創建對象。新添加類時,不會影響以前的系統代碼。核心思想是用一個工廠來根據輸入的條件產生不同的類,然後根據不同類的virtual函數得到不同的結果。
GOOD:適用於不同情況創建不同的類時
BUG:客戶端必須要知道基類和工廠類,耦合性差
(工廠類與基類爲關聯關係)
例:
//基類
class COperation
{
public:
int m_nFirst;
int m_nSecond;
virtual double GetResult()
{
double dResult=0;
return dResult;
}
};
//加法
classAddOperation : public COperation
{
public:
virtual double GetResult()
{
return m_nFirst+m_nSecond;
}
};
//減法
classSubOperation : public COperation
{
public:
virtual double GetResult()
{
return m_nFirst-m_nSecond;
}
};
//工廠類
class CCalculatorFactory
{
public:
staticCOperation* Create(char cOperator);
};
COperation* CCalculatorFactory::Create(char cOperator)
{
COperation *oper;
//在C#中可以用反射來取消判斷時用的switch,在C++中用什麼呢?RTTI??
switch (cOperator)
{
case '+':
oper=newAddOperation();
break;
case '-':
oper=newSubOperation();
break;
default:
oper=newAddOperation();
break;
}
return oper;
}
客戶端
int main()
{
int a,b;
cin>>a>>b;
COperation *op=CCalculatorFactory::Create('-');
op->m_nFirst=a;
op->m_nSecond=b;
cout<<op->GetResult()<<endl;
return 0;
}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------策略模式
定義算法家族,分別封裝起來,讓它們之間可以互相替換,讓算法變化,不會影響到用戶
GOOD:適合類中的成員以方法爲主,算法經常變動;簡化了單元測試(因爲每個算法都有自己的類,可以通過自己的接口單獨測試。
策略模式和簡單工廠基本相同,但簡單工廠模式只能解決對象創建問題,對於經常變動的算法應使用策略模式。
BUG:客戶端要做出判斷
//策略基類
class COperation
{
public:
int m_nFirst;
int m_nSecond;
virtual double GetResult()
{
double dResult=0;
return dResult;
}
};
//策略具體類—加法類
classAddOperation : public COperation
{
public:
AddOperation(int a,int b)
{
m_nFirst=a;
m_nSecond=b;
}
virtual double GetResult()
{
return m_nFirst+m_nSecond;
}
};
class Context
{
private:
COperation* op;
public:
Context(COperation*temp)
{
op=temp;
}
doubleGetResult()
{
returnop->GetResult();
}
};
//客戶端
int main()
{
int a,b;
char c;
cin>>a>>b;
cout<<”請輸入運算符:;
cin>>c;
switch(c)
{
case ‘+’:
Context *context=newContext(new AddOperation(a,b));
cout<<context->GetResult()<<endl;
break;
default:
break;
}
return 0;
}
策略與工廠結合
GOOD:客戶端只需訪問Context類,而不用知道其它任何類信息,實現了低耦合。
在上例基礎上,修改下面內容
class Context
{
private:
COperation* op;
public:
Context(charcType)
{
switch (cType)
{
case '+':
op=newAddOperation(3,8);
break;
default:
op=newAddOperation();
break;
}
}
double GetResult()
{
return op->GetResult();
}
};
//客戶端
int main()
{
int a,b;
cin>>a>>b;
Context *test=newContext('+');
cout<<test->GetResult()<<endl;
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
裝飾模式
動態地給一個對象添加一些額外的職責(不重要的功能,只是偶然一次要執行),就增加功能來說,裝飾模式比生成子類更爲靈活。建造過程不穩定,按正確的順序串聯起來進行控制。
GOOD:當你向舊的類中添加新代碼時,一般是爲了添加核心職責或主要行爲。而當需要加入的僅僅是一些特定情況下才會執行的特定的功能時(簡單點就是不是核心應用的功能),就會增加類的複雜度。裝飾模式就是把要添加的附加功能分別放在單獨的類中,並讓這個類包含它要裝飾的對象,當需要執行時,客戶端就可以有選擇地、按順序地使用裝飾功能包裝對象。
#include<string>
#include<iostream>
using namespacestd;
//人
class Person
{
private:
string m_strName;
public:
Person(string strName)
{
m_strName=strName;
}
Person(){}
virtual void Show()
{
cout<<"裝扮的是:"<<m_strName<<endl;
}
};
//裝飾類
class Finery :public Person
{
protected:
Person*m_component;
public:
voidDecorate(Person* component)
{
m_component=component;
}
virtual voidShow()
{
m_component->Show();
}
};
//T恤
class TShirts:public Finery
{
public:
virtual void Show()
{
cout<<"TShirts"<<endl;
m_component->Show();
}
};
//褲子
class BigTrouser:public Finery
{
public:
virtual void Show()
{
cout<<" BigTrouser"<<endl;
m_component->Show();
}
};
//客戶端
int main()
{
Person *p=new Person("小李");
BigTrouser *bt=new BigTrouser();
TShirts *ts=new TShirts();
bt->Decorate(p);
ts->Decorate(bt);
ts->Show();
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------代理模式
GOOD:遠程代理,可以隱藏一個對象在不同地址空間的事實
虛擬代理:通過代理來存放需要很長時間實例化的對象
安全代理:用來控制真實對象的訪問權限
智能引用:當調用真實對象時,代理處理另外一些事
#include<string>
#include<iostream>
using namespacestd;
//定義接口
class Interface
{
public:
virtual void Request()=0;
};
//真實類
class RealClass: public Interface
{
public:
virtual void Request()
{
cout<<"真實的請求"<<endl;
}
};
//代理類
class ProxyClass: public Interface
{
private:
RealClass* m_realClass;
public:
virtual void Request()
{
m_realClass= new RealClass();
m_realClass->Request();
delete m_realClass;
}
};
客戶端:
int main()
{
ProxyClass* test=new ProxyClass();
test->Request();
return 0;
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------工廠方法模式
GOOD:修正了簡單工廠模式中不遵守開放-封閉原則。工廠方法模式把選擇判斷移到了客戶端去實現,如果想添加新功能就不用修改原來的類,直接修改客戶端即可。
#include<string>
#include<iostream>
using namespacestd;
//實例基類,相當於Product(爲了方便,沒用抽象)
class LeiFeng
{
public:
virtual void Sweep()
{
cout<<"雷鋒掃地"<<endl;
}
};
//學雷鋒的大學生,相當於ConcreteProduct
class Student:public LeiFeng
{
public:
virtual void Sweep()
{
cout<<"大學生掃地"<<endl;
}
};
//學雷鋒的志願者,相當於ConcreteProduct
class Volenter:public LeiFeng
{
public :
virtual void Sweep()
{
cout<<"志願者"<<endl;
}
};
//工場基類Creator
class LeiFengFactory
{
public:
virtual LeiFeng*CreateLeiFeng()
{
return newLeiFeng();
}
};
//工場具體類
class StudentFactory : public LeiFengFactory
{
public :
virtual LeiFeng*CreateLeiFeng()
{
return newStudent();
}
};
class VolenterFactory : public LeiFengFactory
{
public:
virtual LeiFeng*CreateLeiFeng()
{
return newVolenter();
}
};
//客戶端
int main()
{
LeiFengFactory *sf=new StudentFactory ();
LeiFeng *s=sf->CreateLeiFeng();
s->Sweep();
delete s;
delete sf;
return 0;
}
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------原型模式
GOOD:從一個對象再創建另外一個可定製的對象,而無需知道任何創建的細節。並能提高創建的性能。說白了就COPY技術,把一個對象完整的COPY出一份。
#include<iostream>
#include<vector>
#include<string>
using namespacestd;
class Prototype//抽象基類
{
private:
string m_strName;
public:
Prototype(string strName){ m_strName =strName; }
Prototype() { m_strName = " ";}
void Show()
{
cout<<m_strName<<endl;
}
virtualPrototype* Clone() = 0 ;
} ;
// classConcretePrototype1
classConcretePrototype1 : public Prototype
{
public:
ConcretePrototype1(string strName) :Prototype(strName){}
ConcretePrototype1(){}
virtualPrototype* Clone()
{
ConcretePrototype1*p = new ConcretePrototype1() ;
*p = *this; //複製對象
return p ;
}
} ;
// classConcretePrototype2
classConcretePrototype2 : public Prototype
{
public:
ConcretePrototype2(string strName) :Prototype(strName){}
ConcretePrototype2(){}
virtual Prototype* Clone()
{
ConcretePrototype2 *p = newConcretePrototype2() ;
*p = *this ; //複製對象
return p ;
}
} ;
//客戶端
int main()
{
ConcretePrototype1* test = newConcretePrototype1("小王");
ConcretePrototype2*test2 = (ConcretePrototype2*)test->Clone();
test->Show();
test2->Show();
return 0;
}