[读书笔记]大话设计模式(程杰)
https://github.com/iyjhabc/Design-Pattern
第一章:簡單工廠模式
使用一個工廠類來根據(jù)參數(shù)調用不同的函數(shù)。因此增加功能時只需改變工廠類以及新增函數(shù)即可。
class oper
{
protected://使用保護成員,子類可以訪問。子類不能訪問私有成員
double lhs;
double rhs;
public:
double virtual getResult()=0;//純虛函數(shù)
void set_lhs(double lhs){this->lhs=lhs;}
void set_rhs(double rhs){this->rhs=rhs;}
};
class oper_add:public oper
{
public:
double getResult(){
return lhs+rhs;
}
};
class oper_minus:public oper
{
public:
double getResult(){
return lhs-rhs;
}
};
class factory
{
oper *op;
public:
factory(){op=NULL;}
~factory(){if(op)delete op;}
oper* createOperator(char oper_char){
switch(oper_char){
case '+':op=new oper_add;break;
case '-':op=new oper_minus;break;
default:cout<<"operator error"<<endl;
}
return op;
}
};
//用戶代碼,計算器
double clientCounter(double lhs,double rhs,char oper_char){
factory fac;
oper *op=fac.createOperator(oper_char);
if(op==NULL)return 0;
op->set_lhs(lhs);
op->set_rhs(rhs);
return op->getResult();//使用父類指針調用純虛函數(shù)實現(xiàn)多態(tài)
}
第二章:策略模式
使用于對同一對象使用多種算法。而且算法經常需要修改或者替換。策略模式能使用戶代碼與算法隔離,修改算法代碼不需要修改用戶代碼。
class Strategy
{
public:
virtual double algorithm(double cash){//虛函數(shù),用戶實現(xiàn)多態(tài)
return cash;
}
};
class StrategyA:public Strategy
{
public:
double algorithm(double cash){
return 0.8*cash;//八折
}
};
class StrategyB:public Strategy
{
public:
double algorithm(double cash){
return cash>=100?cash-30:cash;//滿100減30
}
};
class Context
{
Strategy *stra;
public:
void loadStrategy(Strategy *s){//加載算法
stra=s;
}
double getResult(double cash,int mode){
switch(mode){
case 0:
this->loadStrategy(new StrategyA);break;
case 1:
this->loadStrategy(new StrategyB);break;
default:
this->loadStrategy(new Strategy);
}
return stra->algorithm(cash);
}
Context(){stra=NULL;}
~Context(){if(stra)delete stra;}
};
//用戶只需維護context類。如要增加算法,只需修改context類并給出新的算法類即可。
//用戶接觸不到算法,實現(xiàn)了算法與用戶的隔離。修改算法的時候也無需修改用戶代碼
double clientFunction(double cash,int mode){
Context context;
return context.getResult(cash,mode);
}
第三章:單一職責原則
一個類只負責一個單一的職責,只能因為特定一種業(yè)務需該改變時才需要修改類。單一職責原則使代碼耦合度降低,便于維護和復用。
第四章:開放-封閉原則
對擴展開放,對修改封閉。新增功能時,應該以添加新的類來實現(xiàn),而不是修改原有代碼。
第五章:依賴倒轉原則(里氏代換原則)
抽象不應該依賴于細節(jié),細節(jié)依賴于抽象。針對接口與抽象類編程,而不是針對實現(xiàn)編程。
依賴翻轉原則實現(xiàn)的基礎:里氏代換原則-如果父類都替換成它的子類,軟件不會有任何問題。例如貓狗養(yǎng)豬都抽象于動物類,當我們的對象從貓換成狗時,由于他們符合里氏代換原則,其他代碼不必修改。
第六章:裝飾模式
裝飾模式能夠為對象動態(tài)地、有序地新增一些功能。用戶代碼可以自主地新增功能(用戶關心的是以什么順序增添什么新功能,并不是功能的具體實現(xiàn)),新增功能時只需添加新的裝飾實體類即可,分離了用戶的核心功能與個別的裝飾功能,而且每種裝飾也容易復用。
class Component
{
public:
virtual void operation()=0;
};
//具體的對象
class ConcreteComponent:public Component
{
public:
void operation(){cout<<"I am a man"<<endl;}
};
//裝飾類
class Decorator:public Component
{
protected:
Component *comp;
public:
Decorator(){comp=NULL;}
~Decorator(){if(comp)delete comp;}
void set_component(Component *comp){
this->comp=comp;
}
void operation(){
if(comp)comp->operation();//關鍵,運行set_component所設置的行為
}
};
//具體裝飾類A,穿衣服
class ConcreteDecoratorA:public Decorator
{
public:
void operation(){
Decorator::operation();//執(zhí)行之前的裝飾
cout<<"dress clothes"<<endl;//本裝飾類自有的行動
}
};
//具體裝飾類B,穿褲子
class ConcreteDecoratorB:public Decorator
{
public:
void operation(){
Decorator::operation();//執(zhí)行之前的裝飾
cout<<"dress trousers"<<endl;//本裝飾類自有的行動
}
};
//客戶端代碼,穿著函數(shù)
void clientDress(){
ConcreteComponent man;
ConcreteDecoratorA *decA=new ConcreteDecoratorA;
ConcreteDecoratorB *decB=new ConcreteDecoratorB;
decA->set_component(&man);//decA父類的comp設置成了man,operation為man的行為
decB->set_component(decA);//decB父類的conp設置成了decA,operation為decA的行為
decB->operation();//先運行祖先decA的operation,而A的operation則先要運行祖先man的。
delete decA;//因此先man->opertion,再A->opertion,再B->opertion
delete decB;//其實就是通過set_component每層改變comp為不同的實體裝飾
}
第七章:代理模式
設計模式中定義: 為其他對象提供一種代理以控制對這個對象的訪問(提供一個殼)。
1) 遠程代理(Remote Proxy)為一個位于不同的地址空間的對象提供一個本地的代理對象。例如網(wǎng)站加載大圖片時可先加載包含圖片位置與尺寸的代理,網(wǎng)站順利顯示后再下載大圖片,增加網(wǎng)站響應速度。
2) 虛擬代理(Virtual Proxy)根據(jù)需要創(chuàng)建開銷很大的對象。如果需要創(chuàng)建一個資源消耗較大的對象,先創(chuàng)建一個消耗相對較小的代理對象來表示,真實對象只在需要時才會被真正創(chuàng)建。延遲創(chuàng)建真實的消耗大的對象提高系統(tǒng)系敖律。
3) 保護代理(Protection Proxy)控制對原始對象的訪問。保護代理用于對象應該有不同的訪問權限的時候。
4) 智能指引(Smart Reference)取代了簡單的指針,它在訪問對象時執(zhí)行一些附加操作。
代理模式能夠協(xié)調調用者和被調用者,在一定程度上降低了系統(tǒng)的耦合度。
//抽象父類
class Subject
{
public:
void virtual request()=0;
};
//真實對象類
class Real_subject:public Subject
{
public:
void request(){
cout<<"my real request"<<endl;
}
};
//代理類
class Proxy:public Subject
{
Real_subject *subject;
public:
void request(){
if(subject==NULL)subject=new Real_subject;//延遲創(chuàng)建Realsubject,用時才創(chuàng)建
cout<<"I am a proxy"<<endl;//通過代理可以添加或屏蔽真實對象的功能
subject->request();
}
Proxy(){subject=NULL;}
~Proxy(){if(subject)delete subject;}
};
//客戶端代碼
void dosomething(Subject &subject){
subject.request();
}
int main(){
Proxy proxy;
dosomething(proxy);
return 0;
}
第八章:工廠方法模式
與簡單工廠模式的區(qū)別是,工廠變成一個抽象類,各種功能再獨自繼承功能工廠類。工廠類不再判斷需要返回什么功能類指針,這個判斷交給客戶代碼。如此一來新增功能時,只需增加新的方法子類,新工廠子類以及修改客戶代碼,不需像簡單工廠模式那樣修改工廠類的代碼,更加符合開放-封閉原則。
代碼跟簡單工廠差不多:https://github.com/iyjhabc/Design-Pattern/blob/master/factory_mothod_pattern.cpp
第九章:原型模式
原型模式提供了一個淺復制的克隆接口,繼承接口的子類可以把原型的當前狀態(tài)復制到克隆體
優(yōu)點:1、克隆直接復制內存,不調用構造函數(shù),可以快速克隆初始化開銷巨大的對象;2、由于直接復制內存,克隆體跟原型的當前狀態(tài)完全一致,因此可以動態(tài)地根據(jù)需要克隆,而不是新建一個初始狀態(tài)的對象。
注意:克隆提供的是淺復制,就是引用指針這種變量只是把地址直接復制到克隆體,他們指向的對象還是原型所指向的。
//可克隆抽象父類
class Prototype
{
public:
virtual Prototype* clone()=0;
static void freeClone(Prototype *pclone){
delete pclone;
}
};
//實際類,如簡歷類
class resume:public Prototype
{
string name;
int &age;//引用類型聲明時必須初始化,因此必須使用初始化列表
string experience;
public:
resume(string name,int &age,string experience):name(name),age(age),experience(experience){}
void set_age(int new_age){
this->age=new_age;
}
void display(){
cout<<this->age<<endl<<this->name<<endl<<this->experience<<endl;
}
Prototype* clone(){//實現(xiàn)深復制的話只能另外new一個resume對象
//因為resume有引用成員變量,引用被初始化以后就不能改變引用目標
resume *presume=(resume*)malloc(sizeof(resume));//直接淺復制,不必調用構造函數(shù)
memcpy(presume,this,sizeof(resume));//也無視訪問權限
return presume;
}
};
int main(){
int age=25;
resume resumeA("yjh",age,"student");
resumeA.display();
resumeA.display();
resumeA.set_age(26);//動態(tài)復制,克隆的結果為最新的值
resume *resumeB=(resume*)resumeA.clone();
resumeB->display();
resumeB->set_age(17);//改變B的age也是也改變了A的
resumeB->display();
resumeA.display();//age=17,淺復制,只復制了地址,克隆體的引用類型還是引用了原型的
Prototype::freeClone(resumeB);
return 0;
}
第十章:模板模式
聲明一個模板抽象類,把固定的操作寫入模板函數(shù)中。把以后可能改變的部分聲明為虛函數(shù),讓子類實現(xiàn),達到代碼復用。
//抽象模板類
class Template
{
public:
virtual void altertableOperation1()=0;//模板中的可變操作部分
virtual void altertableOperation2()=0;
void fixOperation1(){cout<<"fixOperation1 has done"<<endl;}
void fixOperation2(){cout<<"fixOperation2 has done"<<endl;}
void templateMethod(){
fixOperation1();
altertableOperation1();//填空,把以后需要改變的地方聲明為虛函數(shù)
fixOperation2();
altertableOperation2();
}
};
//實際應用模板類A
class concreteClassA:public Template
{
public:
void altertableOperation1(){
cout<<"classA op1 has done"<<endl;
}
void altertableOperation2(){
cout<<"classA op2 has done"<<endl;
}
};
//實際應用模板類B
class concreteClassB:public Template
{
public:
void altertableOperation1(){
cout<<"classB op1 has done"<<endl;
}
void altertableOperation2(){
cout<<"classB op2 has done"<<endl;
}
};
//用戶代碼
void client(){
Template *p=new concreteClassA;
p->templateMethod();
}
第十二章:外觀模式
給同一類子類提供一個簡單的、公共的父類,組合子類的方法(如外觀接口的methodA是子類1、2、4方法的疊加),給用戶提供接口。用戶只需知道外觀接口,不必接觸里面復雜的細節(jié),使代碼便于維護,降低類之間的耦合。
第十三章:建造者模式
用于創(chuàng)建一些復雜的對象,對象內部的建造順序通常是穩(wěn)定的,但內部構建通常面臨著復雜的變化。因此使用構造者來隔離用戶與建造過程,并且使用必須重寫的純虛函數(shù)來規(guī)定每個產品的生產步驟,而細節(jié)必須被重新定制。
class Product
{
string partA;
string partB;
public:
void set_partA(string partA){
this->partA=partA;
}
void set_partB(string partB){
this->partB=partB;
}
void show_product(){
cout<<partA<<" "<<partB<<endl;
}
};
class Builder
{
public:
virtual void set_partA()=0;
virtual void set_partB()=0;
virtual Product* get_product()=0;
};
class ProductBuilderA:public Builder
{
Product *product;
void set_partA(){//必須重寫的純虛函數(shù)
product->set_partA("xx");//私有的,必須利用get_product調用
}
void set_partB(){//確保產品必須被定制
product->set_partB("yy");
}
public:
ProductBuilderA(){
product=new Product;
}
Product*get_product(){//修改此函數(shù)可以改變定制
set_partA();//書中還通過一個director來完成定制,但我感覺集成到這里就可以了
set_partB();
return product;
}
};
void client(){
Builder *builder=new ProductBuilderA;
Product *A=builder->get_product();
A->show_product();
delete builder;
delete A;
}
第十四章:觀察者模式
觀察者模式用于一個類與多個類緊密相關,一個類的狀態(tài)改變了,多個類的狀態(tài)也要協(xié)同改變。使用觀察者模式可以把多類之間的關聯(lián)解耦。使得設計更符合依賴翻轉原則,即依賴于抽象。
class Observer
{
public:
virtual void update()=0;
};
class Subject//用戶可以繼承Subject來表達自己的主題
{
int state;
list<Observer*> observer_list;
public:
void set_state(int new_state){
this->state=new_state;
}
int get_state(){
return this->state;
}
void add_observer(Observer* observer){
observer_list.push_back(observer);
}
void del_observer(Observer* observer){
observer_list.erase(find(observer_list.begin(),observer_list.end(),observer));
}
void notify(){
for(list<Observer*>::iterator it=observer_list.begin();it!=observer_list.end();++it){
(*it)->update();//由subject統(tǒng)一更新observer
}
}
};
class concreteObserverA:public Observer
{
public:
void update(){
cout<<"concreteObserverA is updated"<<endl;
}
};
class concreteObserverB:public Observer
{
public:
void update(){
cout<<"concreteObserverB is updated"<<endl;
}
};
void client(){
Observer *observerA=new concreteObserverA;
Observer *observerB=new concreteObserverB;
Subject *subject=new Subject;
subject->add_observer(observerA);
subject->add_observer(observerB);
subject->set_state(1);
if(subject->get_state()){//如果狀態(tài)改變了,所有的observer需要協(xié)同改變
subject->notify();
}
delete observerA;
delete observerB;
delete subject;
}
總結
以上是生活随笔為你收集整理的[读书笔记]大话设计模式(程杰)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux添加静态路由表,重启继续生效(
- 下一篇: 二极管特性的仿真实验