主目錄:一個面向對象設計(OOD)的學習思路設計c++
引入:bash
老手機:
大家這些年輕手機光溜溜的,全身上下只有兩個插孔幾個按鈕,爲啥這麼受歡迎?新手機:
老前輩,您雖然佔了一半都是按鈕,能夠快速的點到,可是多數狀況下都沒用呀!我雖然只有幾個按鈕,但都是常常用到滴。我也能達到和你同樣的效果,並且更簡潔。老手機:
恩,人們只有打字的時候纔用到那些按鈕。新手機:
因此在日常時候,我這幾個按鈕就能夠知足大部分須要了。老手機:
真是一代比一代強咯!ide
好比圖2-1
中的鴕鳥類不該該被迫依賴於不使用的飛翔方法 學習
如今將2-1
的例子中的接口鳥
進行拆分,能飛的鳥類麻雀
實現接口飛鳥
,不能飛的鳥類鴕鳥
實現接口鳥
,以下圖2-2
所示。ui
不遵循ISP而致使的一些問題,在圖2-1
中,鴕鳥是不須要飛的,但保留了飛的方法。this
如今接口中的飛()
方法須要進行改動,假如改爲:boolean fly()
---能夠理解爲調用一次向上飛,再調用一次向下飛,依次循環。spa
如今不只會飛的鳥須要改動,連鴕鳥這些不會飛的鳥都要莫名奇妙的跟着去改動。設計
顯然這致使了程序之間的耦合加強,影響到了不該該影響的客戶程序code
如今正過來看遵循ISP接口,如圖2-2
所示的例子,分離了方法飛
,使得更改時並不會影響到不相干的客戶程序(鴕鳥類)
對象
須要儘量避免這種耦合,所以咱們但願分離接口。
能夠看出,分離接口有利於咱們對需求變動時的快速高效的執行行動。
而且使之解構層次更加的分明
以ATM用戶界面爲例
Transaction
(交易類)中派生子類:DepositTransaction
存款WithdrawalTransaction
取款TransferTransaction
轉帳圖4-2-1
所示。
Transaction
子類的改動都會迫使對UI進行改動,從而影響到了其餘全部Transaction
子類及其餘全部依賴於UI接口的類。Transaction
的子類所有依賴於UI接口,因此它們都須要從新編譯。DepositUI
、WithdrawalUI
以及TransferUI
這樣的單獨接口,能夠避免這種不合適的耦合,最終的UI接口能夠去多重繼承這些單獨的接口。圖5-3-1
和以後的代碼展現了這個模型。
定義交易接口
/** 存款UI接口*/
interface DepositUI {
void RequestDepositAmount();
}
/** 取款UI接口*/
interface WithdrawalUI {
void RequestWithdrawalAmount();
}
/** 轉帳UI接口*/
interface TransferUI {
void RequestTransferAmount();
}
/** UI接口繼承全部的交易接口*/
interface UI extends DepositUI, WithdrawalUI, TransferUI{
}
複製代碼
交易抽象類
/** 交易類*/
abstract class Transaction {
public abstract void Execute();
}
複製代碼
交易派生類
/** 存款交易類*/
class DepositTransaction extends Transaction {
private DepositUI mDepositUI;
public DepositTransaction(DepositUI mDepositUI) {
this.mDepositUI = mDepositUI;
}
@Override
public void Execute() {
//...
mDepositUI.RequestDepositAmount();
//...
}
}
/** 取款交易類*/
class WithdrawalTransaction extends Transaction {
private WithdrawalUI mWithdrawalUI;
public WithdrawalTransaction(WithdrawalUI mWithdrawalUI) {
this.mWithdrawalUI = mWithdrawalUI;
}
@Override
public void Execute() {
//...
mWithdrawalUI.RequestWithdrawalAmount();
//...
}
}
/** 轉帳交易類*/
class TransferTransaction extends Transaction {
private TransferUI mTransferUI;
public TransferTransaction(TransferUI mTransferUI) {
this.mTransferUI = mTransferUI;
}
@Override
public void Execute() {
//...
mTransferUI.RequestTransferAmount();
//...
}
}
複製代碼
建立交易對象:因爲每一個操做都必須以特定的方式知曉UI版本,如
TransferTransaction
必須知道TransferUI
。在程序中,使每一個操做的構造時給它傳入指向特定於它的UI的引用,從而解決這個問題。以下進行初始化
UI GUI;
void fun() {
DepositTransaction mDepositTransaction = new DepositTransaction(GUI);
}
複製代碼
雖然這樣很方便,但一樣要求每一個操做都有一個指向對應UI的引用成員。另一種解決這個問題的方法是建立一組全局常量。全局變量並不老是意味着拙劣的設計,在這種狀況下,它們有着明顯的易於訪問的有點。
/** UI全局變量*/
class UIGlobals {
public static DepositUI mDepositUI;
public static WithdrawalUI mWithdrawalUI;
public static TransferUI mTransferUI;
public UIGlobals(UI lui) {
UIGlobals.mDepositUI = lui;
UIGlobals.mWithdrawalUI = lui;
UIGlobals.mTransferUI = lui;
}
}
複製代碼
/** 轉帳交易類*/
class TransferTransaction extends Transaction {
@Override
public void Execute() {
//...
UIGlobals.mTransferUI.RequestTransferAmount();
//...
}
}
複製代碼
/**
* UI的實現類
*/
class UIEntity implements UI {
@Override
public void RequestDepositAmount() {
//...
}
@Override
public void RequestTransferAmount() {
//...
}
@Override
public void RequestWithdrawalAmount() {
//...
}
}
複製代碼
/**
* 使用
*/
class A {
//初始化UI靜態類
UIGlobals mUIGlobals = new UIGlobals(new UIEntity());
//調用姿式
void fun() {
Transaction mTransaction = new TransferTransaction();
mTransaction.Execute();
}
}
複製代碼
因爲敏捷軟件開發舉的例子是c++的,知識有限,表示不少看不懂,可能有些地方誤差較大,想了解更多建議親自去看看( ¯▽¯;)
胖類(fat class):就是上邊講解的不知足ISP的類型
能夠看出胖類加強了類之間的耦合,使得對該胖類進行改動會影響到全部其餘類。
經過將胖類接口分解成多個特定類(客戶端程序)的接口,使得強耦合得以解決
而後該胖類繼承全部特定類的接口,並實現它們。就解除了這個特定類和它沒有調用方法間的依賴關係,並使得這些特定類之間互不依賴。
[^foot1]: 敏捷軟件開發 第12章 接口隔離原則(ISP) [^foot2]: 如何向妻子解釋OOD