GEEKBAND 設(shè)計(jì)模式第一周

面向?qū)ο笤O(shè)計(jì)原則

依賴倒置原則

  • 高層模塊(穩(wěn)定)不應(yīng)該依賴低層模塊(變化)吁讨,二者都應(yīng)該依賴于抽象(穩(wěn)定)
  • 抽象(穩(wěn)定)不應(yīng)該依賴于實(shí)現(xiàn)細(xì)節(jié)(變化)花墩,實(shí)現(xiàn)細(xì)節(jié)應(yīng)該依賴于抽象(穩(wěn)定)
  • 分解:大問題分解成小問題阔馋,在面向過程的設(shè)計(jì)中使用。
  • 抽象:忽略細(xì)節(jié)只抓重點(diǎn)去處理泛化的哮幢、理想化的模型贬丛,在面向?qū)ο笾惺褂谩?/li>
  • 畫圖操作中,高層模塊為main的畫圖操作鹃共,底層模塊為各種形狀類鬼佣,抽象為Shape基類;main和形狀都依賴于Shape基類霜浴,而Shape基類獨(dú)立于具體形狀類型晶衷。軟件需求改變時(shí),要改變低層模塊,而不是抽象或是高層模塊

開放封閉原則

  • 對(duì)擴(kuò)展開放晌纫,對(duì)更改封閉
  • 類模塊應(yīng)該是可擴(kuò)展的税迷,但是不可修改
  • 設(shè)計(jì)者可以通過增加內(nèi)容進(jìn)行擴(kuò)展,而不需要在各段代碼中修改東西

單一職責(zé)原則

  • 類應(yīng)該僅有一個(gè)引起他變化的原因
  • 變化的方向隱含著類的責(zé)任

替換原則

  • 子類必須能夠替換他們的基類(IS-A)
  • 繼承表達(dá)類型抽象
  • 所有需要父類的地方锹漱,作為子類都應(yīng)該能夠使用

接口隔離原則

  • 不應(yīng)該強(qiáng)迫客戶程序依賴他們不用的方法
  • 接口應(yīng)該小而完備
  • 不必要的方法不要public

優(yōu)先使用對(duì)象組合箭养,而不是類繼承

  • 繼承在某種程度上破壞了封裝性,子類父類耦合度高
  • 對(duì)象組合則只要求被組合的對(duì)象具有良好定義的接口哥牍,耦合度低

封裝變化點(diǎn)

  • 使用封裝來創(chuàng)建對(duì)象之間的分界層毕泌,讓設(shè)計(jì)者可以在分界層一側(cè)進(jìn)行修改,而不會(huì)對(duì)另一側(cè)產(chǎn)生不良影響嗅辣,從而實(shí)現(xiàn)層次間的松耦合

針對(duì)接口編程撼泛,而不是針對(duì)實(shí)現(xiàn)編程


模版方法::組件協(xié)作

class Library**{**
public**:**
    //穩(wěn)定 template method
void Run**(){**
Step1**();**
**if** **(**Step2**())** **{** //支持變化 ==> 虛函數(shù)的多態(tài)調(diào)用
Step3**();**
**}**
**for** **(**int i **=** 0**;** i **<** 4**;** i**++){**
Step4**();** //支持變化 ==> 虛函數(shù)的多態(tài)調(diào)用
**}**
Step5**();**
**}**
    virtual **~**Library**(){** **}**
protected**:**
    void Step1**()** **{** //穩(wěn)定
//.....
**}**
    void Step3**()** **{**//穩(wěn)定
//.....
**}**
    void Step5**()** **{** //穩(wěn)定
        //.....
    **}**
virtual bool Step2**()** **=** 0**;**//變化
virtual void Step4**()** **=**0**;** //變化
**};**

策略模式

  • 定義一系列算法,把他們一個(gè)個(gè)封裝起來澡谭,并且使他們可以互相替換(變化)愿题。改模式使得算法可以獨(dú)立于使用它的客戶程序(穩(wěn)定)而變化(擴(kuò)展,子類化)
  • 用改模式替換多種switch
class TaxStrategy**{**
public**:**
virtual double Calculate**(**const Context**&** context**)=**0**;** //純虛算法
virtual **~**TaxStrategy**(){}**
**};**
 
 
class CNTax **:** public TaxStrategy**{**
public**:**
virtual double Calculate**(**const Context**&** context**){**
//***********
**}**
**};**
//擴(kuò)展
//*********************************
class FRTax **:** public TaxStrategy**{**
public**:**
    virtual double Calculate**(**const Context**&** context**){**
        //.........
    **}**
**};**
 
//使用****
class SalesOrder**{**
private**:**
TaxStrategy***** strategy**;**
 
public**:**
****//利用工廠模式(以后學(xué)到)來動(dòng)態(tài)得到一個(gè)堆對(duì)象蛙奖,這里暫時(shí)不表潘酗。****
SalesOrder**(**StrategyFactory***** strategyFactory**){**
**this->**strategy **=** strategyFactory**->**NewStrategy**();**
**}**
**~**SalesOrder**(){**
**delete** **this->**strategy**;**
**}**
 
public double CalculateTax**(){**
//...
Context context**();**
 
double val **=**
strategy**->**Calculate**(**context**);** //多態(tài)
//...
**}**
 
**};**

觀察者模式

  • 定義對(duì)象間的一種一對(duì)多(變化)的依賴關(guān)系以便當(dāng)一個(gè)對(duì)象(Subject)的狀態(tài)發(fā)生變化時(shí),所有依賴于它得對(duì)象都得到通知并自動(dòng)更新
Paste_Image.png
class IProgress**{**// 抽象通知機(jī)制的接口
public**:**
    virtual void DoProgress**(**float value**)=**0**;**
    virtual **~**IProgress**(){}**
**};**
 
 
class FileSplitter
**{**
    string m_filePath**;**
    int m_fileNumber**;**
 
    List**<**IProgress***>** m_iprogressList**;** // 抽象通知機(jī)制外永,支持多個(gè)觀察者
    
public**:**
    FileSplitter**(**const string**&** filePath**,** int fileNumber**)** **:**
        m_filePath**(**filePath**),**
        m_fileNumber**(**fileNumber**){**
 
    **}**
    void split**(){**
        //1.讀取大文件
        //2.分批次向小文件中寫入
        **for** **(**int i **=** 0**;** i **<** m_fileNumber**;** i**++){**
            //...
            float progressValue **=** m_fileNumber**;**
            progressValue **=** **(**i **+** 1**)** **/** progressValue**;**
            onProgress**(**progressValue**);**//發(fā)送通知
        **}**
 
    **}**
 
 
    void addIProgress**(**IProgress***** iprogress**){**
        m_iprogressList**.**push_back**(**iprogress**);**
    **}**
 
    void removeIProgress**(**IProgress***** iprogress**){**
        m_iprogressList**.**remove**(**iprogress**);**
    **}**
 
protected**:**
    virtual void onProgress**(**float value**){** //作為虛方法崎脉,以備將來可能對(duì)分割器進(jìn)行擴(kuò)展
        List**<**IProgress***>::**iterator itor**=**m_iprogressList**.**begin**();**
 
        **while** **(**itor **!=** m_iprogressList**.**end**()** **)**
            **(***itor**)->**DoProgress**(**value**);** //由框架告知控件進(jìn)行數(shù)據(jù)更新
            itor**++;**
        **}**//利用循環(huán)通知所有想要獲取進(jìn)行狀態(tài)的對(duì)象,支持多個(gè)觀察者伯顶。
    **}**
**};**
class MainForm **:** public Form**,** public IProgress
**{**
    TextBox***** txtFilePath**;**
    TextBox***** txtFileNumber**;**
 
    ProgressBar***** progressBar**;**
 
public**:**
    void Button1_Click**(){**
        string filePath **=** txtFilePath**->**getText**();**
        int number **=** atoi**(**txtFileNumber**->**getText**().**c_str**());**
 
        ConsoleNotifier cn**;**
        FileSplitter splitter**(**filePath**,** number**);**
        splitter**.**addIProgress**(this);** //訂閱通知囚灼,添加到Observer的通知列表中
        splitter**.**addIProgress**(&**cn**)**;
        splitter**.**split**();**
        splitter**.**removeIProgress**(this);**
 
    **}**
    virtual void DoProgress**(**float value**){**
        progressBar**->**setValue**(**value**);**
    **}**
**};**
//提供另一種顯示方式。
class ConsoleNotifier **:** public IProgress **{**
public**:**
    virtual void DoProgress**(**float value**){**
        cout **<<** "."**;**
    **}**
**};**

裝飾器

  • 動(dòng)態(tài)(組合)地給 一個(gè)對(duì)象增加些額外的職責(zé)祭衩。 就增加功能而言灶体, Decorator模式比生成子類(繼承)更為靈活(消除重復(fù)代碼&減少子類個(gè)數(shù))
class Stream**{**
 
public:
virtual char Read**(**int number**)=**0**;**
virtual void Seek**(**int position**)=**0**;**
virtual void Write**(**char data**)=**0**;**
 
virtual **~**Stream**(){}**
**};**
 
//主體類
class FileStream**:** public Stream**{**
public**:**
virtual char Read**(**int number**){**
//讀文件流
**}**
virtual void Seek**(**int position**){**
//定位文件流
**}**
virtual void Write**(**char data**){**
//寫文件流
**}**
 
**};**
 
class NetworkStream **:**public Stream**{**
public**:**
virtual char Read**(**int number**){**
//讀網(wǎng)絡(luò)流
**}**
virtual void Seek**(**int position**){**
//定位網(wǎng)絡(luò)流
**}**
virtual void Write**(**char data**){**
//寫網(wǎng)絡(luò)流
**}**
 
**};**
//擴(kuò)展操作,使用傳統(tǒng)方法掐暮,存在大量的重復(fù)代碼蝎抽。。
class CryptoFileStream **:**public FileStream**{**
public**:**
virtual char Read**(**int number**){**
//額外的加密操作...
FileStream**::**Read**(**number**);**//讀文件流
**}**
virtual void Seek**(**int position**){**
//額外的加密操作...
FileStream**::**Seek**(**position**);**//定位文件流
//額外的加密操作...
**}**
virtual void Write**(**byte data**){**
//額外的加密操作...
FileStream**::**Write**(**data**);**//寫文件流
//額外的加密操作...
**}**
**};**
 
class CryptoNetworkStream **:** **:**public NetworkStream**{**
public**:**
virtual char Read**(**int number**){**
 
//額外的加密操作...
NetworkStream**::**Read**(**number**);**//讀網(wǎng)絡(luò)流
**}**
virtual void Seek**(**int position**){**
//額外的加密操作...
NetworkStream**::**Seek**(**position**);**//定位網(wǎng)絡(luò)流
//額外的加密操作...
**}**
virtual void Write**(**byte data**){**
//額外的加密操作...
NetworkStream**::**Write**(**data**);**//寫網(wǎng)絡(luò)流
//額外的加密操作...
**}**
**};**//每種流的同樣處理卻要用很多段不同的代碼路克。
======================================================================
//擴(kuò)展操作樟结,應(yīng)用裝飾器。
//使用繼承的目的在于精算,只有通過繼承才能改寫虛函數(shù)Read瓢宦,Seek等;如果是再重新定義一個(gè)Read灰羽,Seek操作驮履,則有裝飾流和無裝飾流不從屬于個(gè)基類鱼辙,無法放在一個(gè)容器里實(shí)現(xiàn)多態(tài)。
//實(shí)用組合的目的在于玫镐,可以把具體的被裝飾類延遲到運(yùn)行時(shí)決定倒戏,而不用靜態(tài)的決定好。(因?yàn)槔^承一定是靜態(tài)的恐似,組合可以是動(dòng)態(tài)的杜跷。)
 
DecoratorStream**:** public Stream**{**
//作為基類的第一派生類(中間類),為其賦予一個(gè)委托蹂喻。
//stream對(duì)象也可以直接扔在下面的加密流中葱椭,不過考慮到可能還有內(nèi)存流,緩沖流等其他的//流口四,他們都要有這樣一個(gè)委托孵运。根據(jù)馬丁福勒的重構(gòu)理論,同一基類的不同子類中的相同元//素應(yīng)該"往上提"蔓彩。
protected**:**
Stream***** stream**;**//...
DecoratorStream**(**Stream ***** stm**):**stream**(**stm**){**
**}**
 
**};**
 
class CryptoStream**:** public DecoratorStream **{**
 
public**:**
CryptoStream**(**Stream***** stm**):**DecoratorStream**(**stm**){**
**}**
virtual char Read**(**int number**){**
 
//額外的加密操作...
stream**->**Read**(**number**);**//讀文件流
**}**
virtual void Seek**(**int position**){**
//額外的加密操作...
stream**::**Seek**(**position**);**//定位文件流
//額外的加密操作...
**}**
virtual void Write**(**byte data**){**
//額外的加密操作...
stream**::**Write**(**data**);**//寫文件流
//額外的加密操作...
**}**
**};**//所有的流都可以用這個(gè)類進(jìn)行裝飾旷赖,只需要把流指定為基類的成員。
void Process**(){**
 
//運(yùn)行時(shí)裝配
FileStream***** s1**=new** FileStream**();**
 
CryptoStream***** s2**=new** CryptoStream**(**s1**);**
//使用時(shí)最外層應(yīng)該是裝飾器俯萌。
 
**}**

橋模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市辨萍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌爪飘,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡顷窒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門鞋吉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來坛掠,“玉大人,你說我怎么就攤上這事∮蚶模” “怎么了酬土?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵刹枉,是天一觀的道長微宝。 經(jīng)常有香客問我岳守,道長譬重,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任臀规,我火速辦了婚禮滩援,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘以现。我一直安慰自己狠怨,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布邑遏。 她就那樣靜靜地躺著佣赖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪记盒。 梳的紋絲不亂的頭發(fā)上憎蛤,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音纪吮,去河邊找鬼俩檬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛碾盟,可吹牛的內(nèi)容都是我干的棚辽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼冰肴,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼屈藐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起熙尉,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤联逻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后检痰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體包归,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年铅歼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了公壤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片换可。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖境钟,靈堂內(nèi)的尸體忽然破棺而出锦担,到底是詐尸還是另有隱情,我是刑警寧澤慨削,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站套媚,受9級(jí)特大地震影響缚态,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜堤瘤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一玫芦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧本辐,春花似錦桥帆、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至茫多,卻和暖如春祈匙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背天揖。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工夺欲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人今膊。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓些阅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斑唬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子市埋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)赖钞,斷路器腰素,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • C++設(shè)計(jì)模式 為了理解松耦合設(shè)計(jì)思想,掌握面向?qū)ο笤O(shè)計(jì)原則 什么是設(shè)計(jì)模式雪营? 是一種解決方案的核心弓千,可以避免重復(fù)...
    古來征戰(zhàn)幾人回閱讀 361評(píng)論 0 0
  • 23種設(shè)計(jì)模式 “對(duì)象性能”模式 面向?qū)ο蠛芎玫慕鉀Q了“抽象”的問題,但是必不可免地要付出一定的代價(jià)献起。對(duì)于通常情況...
    孫浩_9bfd閱讀 381評(píng)論 0 0
  • ## 可重入函數(shù) ### 可重入性的理解 若一個(gè)程序或子程序可以安全的被并行執(zhí)行洋访,則稱其為可重入的镣陕;即當(dāng)該子程序正...
    夏至亦韻閱讀 698評(píng)論 0 0
  • 武夷山門票淡季半價(jià)160元,三日門票含景區(qū)費(fèi)和車費(fèi)姻政,九曲江漂流的費(fèi)用130元/人呆抑,1.1米以上兒童全票。 武夷山景...
    丟寶手絹閱讀 413評(píng)論 0 0