面向?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ò)展,子類化)
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)更新
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)系作者