類設(shè)計(jì)考慮的問(wèn)題
1.類的組織與表示
聚類分析、類的再抽象涮俄、類的拆分、類的復(fù)用性... ...
2.行為的組織與表示
行為的分解、行為的參與者合搅、行為的分組與接口兢哭、行為的差異... ...
3.屬性的組織與表示
復(fù)合屬性不铆、只讀只寫(xiě)屬性暂题、不變屬性、運(yùn)行時(shí)屬性... ...
變化與復(fù)用
1.變化
職責(zé)的變化(接口喜喂、功能)
實(shí)現(xiàn)的變化(數(shù)據(jù)表示瓤摧、行為)
2.變化的適應(yīng)方式
擴(kuò)展既有代碼:繼承、關(guān)聯(lián)玉吁、依賴照弥、聚合、組合
直接修改代碼的問(wèn)題:獲取既有代碼进副、改變實(shí)現(xiàn)的顧慮这揣、改變接口的顧慮
設(shè)計(jì)模式基本原則
抽象與封裝原則:
分離穩(wěn)定與變化
封裝變化
抽象變化接口
針對(duì)接口編程而不針對(duì)實(shí)現(xiàn)編程
組合優(yōu)先原則(而不是繼承)
類的關(guān)系
class A{
public:
void f();
}
關(guān)聯(lián)
class B{
public:
void g();
private:
A*pa;
}
依賴(實(shí)例級(jí)關(guān)聯(lián))
class B{
public:
void g(A&a){ a.f()};
}
組合/聚合(類級(jí)關(guān)聯(lián))
class B{
public:
void g();
private:
A*pA;
}
泛化關(guān)系
實(shí)現(xiàn)關(guān)系
創(chuàng)建型設(shè)計(jì)模式-工廠方法模式
動(dòng)機(jī):
顧客Client類與產(chǎn)品耦合緊密,
產(chǎn)品經(jīng)常變化(增加,添加屬性)
class Client(){
void f(){
Dog*d=new Dog;
}
}
//使用IAnimal接口
class Client(){
void f(){
IAnimal*ani=new Dog;
}
}
//工廠方法1-分離實(shí)例化部分
class Client(){
void f(){
IAnimal*ani=CreateAnimal();
}
virtual IAnimal*CreateAnimal();//工廠方法
}
//工廠方法2-分離實(shí)例化部分
class Client(){
void f(Factory&fac){
IAnimal*ani=fac.CreateAnimal();
}
}
//獨(dú)立出工廠
class Factory{
virtual IAnimal*CreateAnimal();
}
總結(jié)
定義頂層工廠接口给赞,由接口決定產(chǎn)品的創(chuàng)建
優(yōu)點(diǎn):
擴(kuò)展產(chǎn)品支持開(kāi)閉原則(擴(kuò)展開(kāi)發(fā)机打,修改關(guān)閉):新增產(chǎn)品樹(shù)、類片迅;用同構(gòu)產(chǎn)品樹(shù)替換原產(chǎn)品樹(shù)
不足:
繼承導(dǎo)致:子類數(shù)量過(guò)多
創(chuàng)建型設(shè)計(jì)模式-簡(jiǎn)單工廠(靜態(tài)工廠)方法模式
和工廠方法的區(qū)別:
如果產(chǎn)品種類穩(wěn)定残邀,則從Factory派生子類失去意義,所以Factory中的方法成為類方法將更加合理
在實(shí)例化對(duì)象時(shí)柑蛇,如果輸入條件(參數(shù))不一樣罐旗,產(chǎn)生的對(duì)象也不一樣,那么我們可以考慮使用簡(jiǎn)單工廠對(duì)不同的實(shí)例進(jìn)行統(tǒng)一封裝唯蝶。
創(chuàng)建型設(shè)計(jì)模式-單件模式
動(dòng)機(jī):
僅有一個(gè)實(shí)例或至多有N個(gè)實(shí)例
能夠從外部訪問(wèn)它
即程序在運(yùn)行的過(guò)程中,希望在任意時(shí)刻遗嗽,都只保留某個(gè)對(duì)象的唯一實(shí)例
class single{
public:
?static single*instance();
?void f();?
private:
?single(){...}
?single(const single&);//禁用
?single&operator=(const single&);
private:
?static single*instance;
}
single*single::instance=0;
single*single::instance(){
?if(instance==0){
?instance=new instance;
?}
?return instance;
}
創(chuàng)建型設(shè)計(jì)模式-構(gòu)造器/生成器模式
動(dòng)機(jī):
創(chuàng)建復(fù)雜對(duì)象
陳老師的創(chuàng)建墻的例子:
當(dāng)創(chuàng)建墻的時(shí)候粘我,需要?jiǎng)?chuàng)建水泥和磚
采用工廠方法去創(chuàng)建,工廠方法里面包括了:創(chuàng)建水泥和創(chuàng)建磚方法
通過(guò)調(diào)用
factory.創(chuàng)建水泥();
factory.創(chuàng)建磚();
factory.創(chuàng)建水泥();
factory.創(chuàng)建磚();
創(chuàng)建墻
問(wèn)題:在創(chuàng)建墻的過(guò)程中痹换,水泥和磚的創(chuàng)建次數(shù)是不需要知道的
墻構(gòu)造器.創(chuàng)建磚(5){
?循環(huán)5次factory.創(chuàng)建磚();
}
墻構(gòu)造器.創(chuàng)建水泥(5){
循環(huán)5次factory.創(chuàng)建水泥();
}
如果需要適應(yīng)更多的變化征字,比如構(gòu)造一層磚,則可以再抽象 出一個(gè)類
在創(chuàng)建時(shí)娇豫,先生成一個(gè)墻的Builder類匙姜,然后在Director指示器的方法中,選擇要?jiǎng)?chuàng)建的行為冯痢,該行為調(diào)用Builder中的創(chuàng)建方法氮昧,最后返回創(chuàng)建完畢的墻。
使用相同的產(chǎn)品但使用不同的構(gòu)造器浦楣,可以產(chǎn)生不同的復(fù)雜對(duì)象袖肥。
構(gòu)造器隱藏了構(gòu)建的細(xì)節(jié)和裝配的過(guò)程
創(chuàng)建型設(shè)計(jì)模式-原型方法
動(dòng)機(jī):
當(dāng)我們需要?jiǎng)?chuàng)建多次/多個(gè),相同的元素時(shí)振劳。
我們?cè)诔绦蜻\(yùn)行過(guò)程中椎组,當(dāng)需要有新的實(shí)例對(duì)象(但是狀態(tài)基本相同的元素)時(shí)使用。
例子:我的世界中历恐,草坪塊寸癌,變成有積雪覆蓋的草坪塊。
這個(gè)時(shí)候就需要一個(gè)新的圖塊對(duì)象覆蓋原本的塊弱贼。
不同的解決方案:
1.使用構(gòu)造函數(shù)
屬于硬編碼蒸苇,不能動(dòng)態(tài)改變創(chuàng)建的類
2.拷貝/構(gòu)造函數(shù)
new 沙塊(a沙塊);
new 巖石(a巖石)哮洽;
需要知道確切的類型
原型方法:
class BlockManager(){
?private:
?static Sand* aSand;
?static Rock* aRock;
public:
?Block*Create(int id){
? ?if(id==1){return aSand.clone();}
? ?else if(id==2){return aRock.clone();}
?}
}
原型方法可以有效減少子類的數(shù)量填渠,但是事先clone接口可能存在難度。
創(chuàng)建型設(shè)計(jì)模式-抽象工廠方法
動(dòng)機(jī):
如上圖,當(dāng)需要限制氛什,喜歡貓的小孩只能創(chuàng)建貓莺葫。
限制用戶使用同一系列的產(chǎn)品。
(window操作系統(tǒng)下面枪眉,只能使用window下面的鼠標(biāo)捺檬、窗口事件)