保溫管有哪些網(wǎng)站做網(wǎng)絡(luò)推廣員為什么做不長(zhǎng)
前言
? ? ?
? ? ? ? ?在C++的基礎(chǔ)語法的學(xué)習(xí)后,更進(jìn)一步為應(yīng)用場(chǎng)景多寫代碼.其中設(shè)計(jì)模式是有較大應(yīng)用空間.
引入
? ? ? ? 原本在寫容器中適配器類有關(guān)的帖子,發(fā)現(xiàn)適配模式需要先了解,于是試著先寫篇和適配器模式相關(guān)的帖子
?????????理解什么是適配器類,需要知道什么是適配器模式.適配器模式是設(shè)計(jì)模式的一種.筆者也準(zhǔn)備開這個(gè)系列的專題,這里就當(dāng)首個(gè)模式介紹.
從接口說起
? ? ? ? 接口和實(shí)現(xiàn)的關(guān)系如圖所示?
?
?????????
?????????
????????這個(gè)圖可以看成一切設(shè)計(jì)模式的起源.各種設(shè)計(jì)模式都可以從本圖中演化出來----當(dāng)然實(shí)際操作起來會(huì)遠(yuǎn)遠(yuǎn)難于一張圖(筆者的思維習(xí)慣是概念極簡(jiǎn),就好像之前把程序看成只做了兩件事:修改數(shù)據(jù)和映射數(shù)據(jù)到硬件一樣).
? ? ? ? 接口是一種功能,一個(gè)需求;實(shí)現(xiàn)類是一種實(shí)現(xiàn),多個(gè)實(shí)現(xiàn)類是多種實(shí)現(xiàn).就好像變量代表所有能表示的常量.接口和實(shí)現(xiàn)的關(guān)系類似于變量和常量.接口是"虛"的,實(shí)現(xiàn)是"實(shí)"的.
? ? ? ? 舉例:有個(gè)喝下午茶的需求,有中式下午茶,吃龜苓膏,喝涼茶;有西式下午茶,喝咖啡,吃蛋糕.用接口與實(shí)現(xiàn)表達(dá)出來.
/*接口與實(shí)現(xiàn)*/
#include<iostream>
using namespace std;//抽象基類(接口)定義
class Abs_AfternoonTea {
public:virtual void eat() = 0; //純虛方法:功能需求
};//中式下午茶定義
class ChineseTea :public Abs_AfternoonTea{int room_number; //餐廳房間號(hào)碼
public:ChineseTea(int ro) :room_number(ro) {};void Guiling_paste(){ cout << "吃龜苓膏" << endl; }void cold_tea(){cout<< "喝涼茶" << endl;}
// int getRoomNumber() { return room_number; }void eat() { cout << "在" << room_number << "號(hào)房間享用下午茶:" << endl;Guiling_paste();cold_tea();}
};//西式下午茶定義
class WestTea :public Abs_AfternoonTea {int room_number; //餐廳房間號(hào)碼
public:WestTea(int ro) :room_number(ro) {};void coffee() { cout << "喝咖啡" << endl; }void cake() { cout << "吃蛋糕" << endl; }int getRoomNumber() { return room_number; }void eat() {cout << "在" << room_number << "號(hào)房間享用下午茶:" << endl;coffee();cake();}
};
? ? ? ? 測(cè)試代碼
int main(void) {ChineseTea ct(3);Abs_AfternoonTea& aat = ct;aat.eat();
}
----這種方案的是接口和實(shí)現(xiàn)直接對(duì)接,沒問題
? ? 回顧:需求:下午茶; 實(shí)現(xiàn)1:中式下午茶; 實(shí)現(xiàn)2:西式下午茶
? ? 現(xiàn)在喝下午茶的需求做一點(diǎn)改變:喝涼茶,吃蛋糕;(中式西式各占一個(gè)).如果再按"接口-實(shí)現(xiàn)"的方式來設(shè)計(jì)代碼架構(gòu),就得再設(shè)計(jì)一個(gè)類MixTea,如下所示:?
//混合下午茶定義
class MixTea :public Abs_AfternoonTea {int room_number; //餐廳房間號(hào)碼
public:WestTea(int ro) :room_number(ro) {};void cold_tea() { cout << "喝涼茶" << endl; }void cake() { cout << "吃蛋糕" << endl; }void eat() {cout << "在" << room_number << "號(hào)房間享用下午茶:" << endl;cold_tea();cake();}
};
? ? ? ? 測(cè)試代碼:
int main(void) {MixTea mt(3);Abs_AfternoonTea& aat = mt;aat.eat();
}
? ? ? ? 問題并沒有完全解決,如果下次的需求再改變:喝咖啡,吃龜苓膏.又得再設(shè)計(jì)一個(gè)類,依次類推.
? ? ? ? 所以得出結(jié)論:
????????????????接口-實(shí)現(xiàn)的直接架構(gòu)是萬能的,但擴(kuò)展性不好
? ? ? ? 為了讓接口更好地被實(shí)現(xiàn),需要對(duì)現(xiàn)有代碼修改.適配器登場(chǎng).
適配器適應(yīng)方案選擇?
? ? ? ? 適配器思路:接口由適配器實(shí)現(xiàn)(適配器類繼承接口).適配器是一個(gè)間接類,具體怎么實(shí)現(xiàn)由他所包含的對(duì)象來決定.?現(xiàn)在把工作細(xì)化,每個(gè)工作配一個(gè)廚師(龜苓膏,涼茶,咖啡,蛋糕各自由一個(gè)廚師來做).下面是為適配器準(zhǔn)備的類
????????接口和適配器類.h
/*適配器以下類定義*/
#include<iostream>
using namespace std;
/*定義廚師類及派生類*/
class Chef { //廚師類string name;
public:Chef(const string& na):name(na){}string getName() { return name; } //獲得名稱virtual void make_food() {}; //虛方法,做食物
}; class Cake_division :public Chef { //蛋糕師類
public:Cake_division(const string& st) :Chef(st) {}void make_cake() { cout << getName()<<"做蛋糕" << endl; }virtual void make_food(){ make_cake(); }
};class Barista :public Chef { //咖啡師類
public:Barista(const string& st) :Chef(st) {}void make_coffee() { cout << getName() << "沖咖啡" << endl; }virtual void make_food() { make_coffee(); }
};class Guilinggao_master :public Chef { //龜苓膏師傅類
public:Guilinggao_master(const string& st) :Chef(st){}void make_Guilinggao() { cout << getName() << "做龜苓膏" << endl; }virtual void make_food() { make_Guilinggao(); }
};class Herbal_tea_master :public Chef { //涼茶師傅類
public:Herbal_tea_master(const string& st) :Chef(st) {}void make_Herbal_tea() { cout << getName() << "做涼茶" << endl; }virtual void make_food() { make_Herbal_tea(); }
};/*以下為單組食物適配器定義的類*/
class SingleGroup { //單組接口string name;
public:SingleGroup(const string& st):name(st) {}virtual void eat() {};
};class ChineseTeaGroup :public SingleGroup{ //中式下午茶類Guilinggao_master& gm;Herbal_tea_master& hm;
public:ChineseTeaGroup(Guilinggao_master& g, Herbal_tea_master& h, const string& st):gm(g),hm(h), SingleGroup(st){}void eat() { gm.make_food(); hm.make_food(); }
};class WestTeaGroup :public SingleGroup { //西式下午茶類Cake_division& cd;Barista& ba;
public:WestTeaGroup(Cake_division& c, Barista& b, const string& st):cd(c),ba(b),SingleGroup(st){}void eat() { cd.make_food(); ba.make_food(); }
};/*以下為混合食物適配器定義的類*/
/*不想使用多重繼承,用包含把廚師對(duì)象拿過來*/
class MixChineseTeaGroup { //中式下午茶(混合)類string name;
public:MixChineseTeaGroup(const string& st):name(st){}virtual void eat(){}
};class MixGuilinggao:public MixChineseTeaGroup { //龜苓膏(混合)類Guilinggao_master& gm;
public:MixGuilinggao(Guilinggao_master& g,const string& st) :gm(g) ,MixChineseTeaGroup(st){}void eat() { gm.make_food(); }
};class MixHerbal :public MixChineseTeaGroup { //涼茶(混合)類Herbal_tea_master& hm;;
public:MixHerbal(Herbal_tea_master& h, const string& st) :hm(h), MixChineseTeaGroup(st) {}void eat() { hm.make_food(); }
};class MixChineseDouble :public MixChineseTeaGroup { //中式下午茶兩個(gè)一起類Guilinggao_master& gm;Herbal_tea_master& hm;
public:MixChineseDouble(Guilinggao_master& g, Herbal_tea_master& h, const string& st) :gm(g), hm(h), MixChineseTeaGroup(st) {}void eat() { gm.make_food(); hm.make_food(); }
};class MixWestTeaGruop { //西式下午茶(混合)總類string name;
public:MixWestTeaGruop(const string& st) :name(st) {}virtual void eat() {}
};class MixCake :public MixWestTeaGruop { //蛋糕類(混合) Cake_division& cn;
public:MixCake(Cake_division& c, const string& st):cn(c),MixWestTeaGruop(st){}void eat() { cn.make_food(); }
};class MixBarista :public MixWestTeaGruop { //咖啡類(混合)Barista& ba;
public:MixBarista(Barista& b, const string& st) :ba(b), MixWestTeaGruop(st) {}void eat() { ba.make_food(); }
};class MixWestDouble :public MixWestTeaGruop { //西式下午茶兩個(gè)一起類Cake_division& cd;Barista& ba;
public:MixWestDouble(Cake_division& c, Barista& b, const string& st) :cd(c), ba(b), MixWestTeaGruop(st) {}void eat() { cd.make_food(); ba.make_food(); }
};
?接口和適配器類.cpp
/*適配器及接口定義*/
#include<iostream>
#include<string>
#include"接口和適配器.h"
using namespace std;//抽象基類(接口)定義
class Abs_AfternoonTea {
public:virtual void eat() = 0; //純虛方法:功能需求
};//單組適配器定義
class SingleGroup_Adapter :public Abs_AfternoonTea {SingleGroup& sg;
public:SingleGroup_Adapter(SingleGroup& s):sg(s){}virtual void eat() { sg.eat(); }
};//混組適配器定義
class MixGroup_Adapter :public Abs_AfternoonTea {MixChineseTeaGroup& mcg;MixWestTeaGruop& mwg;
public:MixGroup_Adapter(MixChineseTeaGroup& mc, MixWestTeaGruop& mw):mcg(mc),mwg(mw){}virtual void eat() { mcg.eat(); mwg.eat(); }
};//單點(diǎn)適配器定義
class SingleFood_Adapter :public Abs_AfternoonTea {Chef& cf;
public:SingleFood_Adapter(Chef& c):cf(c){}virtual void eat() { cf.make_food(); }
};
????????測(cè)試代碼????????
int main(void) {/*單吃蛋糕*/Cake_division cd("小張"); //生成蛋糕師對(duì)象
// Chef& cf = cd; //廚師對(duì)象生成SingleFood_Adapter sfa(cd); //單點(diǎn)適配器對(duì)象生成Abs_AfternoonTea& aat = sfa; //轉(zhuǎn)向接口aat.eat();cout << "===============分隔線============" << endl;/*中式下午茶組*/Guilinggao_master xw("小王");Herbal_tea_master xl("小李");ChineseTeaGroup cg(xw, xl,"中式下午茶");SingleGroup& sg = cg;SingleGroup_Adapter sa = SingleGroup_Adapter(cg); //單組適配器對(duì)象生成Abs_AfternoonTea& aat1 = sa; //轉(zhuǎn)向接口aat1.eat();cout << "===============分隔線============" << endl;/*混合下午茶*/MixChineseDouble md(xw, xl,"混合下午茶");MixChineseTeaGroup& mtg = md;MixCake mc(cd, "xiaozhang");MixWestTeaGruop& mg = mc;MixGroup_Adapter ma = MixGroup_Adapter(mtg, mg); //混合適配器對(duì)象生成Abs_AfternoonTea& aat2 = ma; //轉(zhuǎn)向接口aat2.eat();
}
================================內(nèi)容分割線================================?
? ? ? ? ?代碼有打磨空間,一是能否去掉不相關(guān)的屬性;二是引入客戶指令---測(cè)試是自己寫的條件,客戶指令處理可以加進(jìn)來
================================內(nèi)容分割線================================?
代碼說明
? ? ? ? 第一,看見密密麻麻的代碼,為了一個(gè)小問題增加許多是否值得?
????????????????代碼多,但是表達(dá)的意思并不是很多,只是看起來多而已.
? ? ? ? ????????值得不值得,這個(gè)得根據(jù)需求來.只要能滿足客戶需求就是值得的.?
? ? ? ? 第二,可以實(shí)現(xiàn)哪些功能?
? ? ? ? ? ? ? ? 1.單個(gè)組合:西式下午茶--咖啡和蛋糕套餐? (或)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?中式下午茶--龜苓膏和涼茶套餐
? ? ? ? ? ? ? ? 2.混合點(diǎn)餐:咖啡,蛋糕,龜苓膏,涼茶任選其二以上(單點(diǎn)不行)
? ? ? ? ? ? ? ? 3.單點(diǎn):咖啡,蛋糕,龜苓膏,涼茶任選其一.
?????????第三,為什么有感覺重復(fù)的類?
? ? ? ? ? ? ? ? 筆者暫時(shí)不會(huì)多重繼承,也不知道多重繼承是否適合.所以定義了多個(gè)類.測(cè)試可以的
關(guān)于適配器模式
? ? ? ? 在接口--實(shí)現(xiàn)的過程中,加了適配器一層.適配器的作用簡(jiǎn)單描述就是繼承接口,包含相關(guān)類?
? ? ? ? 此外,適配器模式容易擴(kuò)展.比如在此代碼基礎(chǔ)上,繼續(xù)用適配器擴(kuò)展,加入更多功能,也是很方便的.?