主目录:一个面向对象设计(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