朱紅梅 王魯
摘? 要:針對(duì)軟件各種設(shè)計(jì)模式的定義不容易被透徹理解和靈活應(yīng)用的問(wèn)題,文章以裝飾設(shè)計(jì)模式為例介紹其教學(xué)過(guò)程,深入解析裝飾設(shè)計(jì)模式的動(dòng)機(jī),通過(guò)教學(xué)案例引入具體問(wèn)題,從一般實(shí)現(xiàn)代碼中發(fā)現(xiàn)存在的問(wèn)題,經(jīng)過(guò)分析和重構(gòu)得出裝飾設(shè)計(jì)模式的結(jié)構(gòu)和要點(diǎn),使學(xué)生對(duì)裝飾設(shè)計(jì)模式有更深入的理解,達(dá)到讓學(xué)生日后可以靈活使用該模式的目的。
關(guān)鍵詞:設(shè)計(jì)模式;裝飾設(shè)計(jì)模式;重構(gòu);教學(xué)過(guò)程
中圖分類號(hào):TP312;G642.0? ? ? 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):2096-4706(2020)09-0101-03
Teaching Process Research of Decorator Design Pattern
ZHU Hongmei,WANG Lu
(College of Information Science and Engineering,Shandong Agricultural University,Taian? 271018,China)
Abstract:Aiming at the problem that the definitions of various software design patterns is not easy to be fully understood and flexibly applied,this paper takes Decorator Design Pattern as an example for teaching process design. The motivation of decoration design pattern is deeply analyzed. A specific problem as teaching case is introduced. From the general implementation of the example existing problems is found. The structure and key points of the decorator design pattern is gotten through analysis and reconstruction,through which the students have a deeper understanding of the decorator design pattern and achieve the purpose of flexible use of it.
Keywords:design pattern;decorator design pattern;reconstruction;teaching process
0? 引? 言
軟件設(shè)計(jì)模式是指在軟件開(kāi)發(fā)中經(jīng)過(guò)驗(yàn)證并用于解決在特定環(huán)境下、重復(fù)出現(xiàn)的、特定問(wèn)題的解決方案,體現(xiàn)了思想級(jí)別的成果復(fù)用[1]。由于對(duì)現(xiàn)代軟件產(chǎn)品的通用性、擴(kuò)展性、復(fù)用性要求越來(lái)越高,軟件開(kāi)發(fā)過(guò)程中需求的不斷變化和深入使得人們?cè)絹?lái)越重視軟件設(shè)計(jì)模式。裝飾(Decotator)設(shè)計(jì)模式,也稱包裝模式,是軟件設(shè)計(jì)模式中的一個(gè)重要的設(shè)計(jì)模式,GoF給出的定義是動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé),就擴(kuò)展對(duì)象的功能來(lái)說(shuō),裝飾設(shè)計(jì)模式比生成子類更為靈活[2]。從定義上來(lái)看,初學(xué)者很難把握。為達(dá)到幫助學(xué)生真正理解裝飾設(shè)計(jì)模式的教學(xué)目標(biāo),教師應(yīng)成為教學(xué)中的導(dǎo)航者、學(xué)生學(xué)習(xí)的幫助者與引路人[3],培養(yǎng)學(xué)生從專業(yè)的角度來(lái)評(píng)價(jià)設(shè)計(jì)方案,引導(dǎo)學(xué)生領(lǐng)悟優(yōu)秀設(shè)計(jì)案例的構(gòu)思過(guò)程[4]。每種模式都有自身獨(dú)特的應(yīng)用場(chǎng)景[5],在教學(xué)過(guò)程中就不能簡(jiǎn)單給出設(shè)計(jì)模式的定義和結(jié)構(gòu)圖,要求學(xué)生照?qǐng)D寫代碼,而是深入解析裝飾設(shè)計(jì)模式的動(dòng)機(jī),通過(guò)實(shí)例引入具體問(wèn)題,通過(guò)對(duì)實(shí)例的分析和重構(gòu)得出裝飾設(shè)計(jì)模式的結(jié)構(gòu)和要點(diǎn)。
1? 裝飾設(shè)計(jì)模式的出發(fā)點(diǎn)
在面向?qū)ο筌浖O(shè)計(jì)中,很自然就會(huì)想到使用繼承來(lái)擴(kuò)展對(duì)象的功能,由于繼承破壞封裝,提高了子類與父類之間的耦合性,隨著擴(kuò)展功能的增多子類也會(huì)增多,擴(kuò)展功能的組合也會(huì)導(dǎo)致出現(xiàn)各種組合的子類,進(jìn)而引發(fā)子類的膨脹。因此,過(guò)度地使用繼承來(lái)擴(kuò)展對(duì)象的功能存在一定的缺陷。
裝飾設(shè)計(jì)模式的目的就是為了在動(dòng)態(tài)擴(kuò)展對(duì)象功能的同時(shí),避免擴(kuò)展功能的增多帶來(lái)子類激增,從而將功能擴(kuò)展這種變化所導(dǎo)致的影響降為最低。
2? 教學(xué)案例設(shè)計(jì)
2.1? 實(shí)例
人來(lái)自不同地區(qū),如北京、上海,不同地區(qū)的人又有各種特性,描述人及其特性。如果有特性:高和富,則有組合:高、富、高富等共3個(gè)特性描述;用繼承實(shí)現(xiàn)的結(jié)構(gòu)圖如圖1所示。如果增加1個(gè)特性:帥,則描述一個(gè)人可以有組合:高、富、帥、高富、高帥、富帥、高富帥等共7個(gè)特性描述。
一般實(shí)現(xiàn):
abstract class Person{ //公共基類
String name;
public abstract void desc();
};
//主體類
class Beijinger extends Person{
public void desc() { System.out.println(name+" 是北京人"); }
};
class Shanghaier extends Person{
public void desc() { System.out.println(name+" 是上海人"); }
};
//擴(kuò)展類
class highBeijinger extends Beijinger{
public void desc() { super.desc(); System.out.println(" 是高個(gè)人"); }
};
class richBeijinger extends Beijinger{
public void desc() { super.desc(); System.out.println(" 是富人"); }
};
class highrichBeijinger extends Beijinger{
public void desc() { super.desc(); System.out.println(" 是高個(gè)富人"); }
};
class HighShanghaier extends Shanghaier{……};
class RichShanghaier extends Shanghaier{……};
class highrichShanghaier extends Shanghaier{……};
public class program {
public static void main(String[] args){
highBeijinger hc = new highBeijinger(); hc.setName("Zhangsan");
richBeijinger rc = new richBeijinger(); rc.setName("Lisi");
hc.desc(); rc.desc();
}
}
假設(shè)n是地區(qū)的個(gè)數(shù),m是特性個(gè)數(shù),則用繼承實(shí)現(xiàn)描述人及其特性需要的類的個(gè)數(shù)是:1+n+n*()=1+n*2m
如果n=2,m=2(高、富),則需要定義1+2*22=9個(gè)
類;如果n=2,m=3(高、富、帥),則需要定義1+2*23= 17個(gè)類??梢?jiàn),用繼承來(lái)擴(kuò)展對(duì)象的功能會(huì)導(dǎo)致子類數(shù)量的急劇膨脹。雖然這種分析非常直觀,但是如果就此直接引入裝飾設(shè)計(jì)模式,學(xué)生難以理解。這就需要把一般實(shí)現(xiàn)的代碼通過(guò)重構(gòu)引出裝飾設(shè)計(jì)模式。
2.2? 分析問(wèn)題重構(gòu)代碼
分析1:觀察一般實(shí)現(xiàn)的代碼可以發(fā)現(xiàn),隨著需求的變化,使用繼承得到的擴(kuò)展使子類急劇增多,同時(shí)充斥著大量重復(fù)代碼。這時(shí)候的關(guān)鍵是劃清責(zé)任,以“高”為例說(shuō)明用組合/聚合代替繼承的實(shí)現(xiàn):
class highBeijinger{
Beijinger person; //用聚合代替繼承
public void desc() { person.desc();System.out.println(" 是高個(gè)人"); }
public highBeijinger(Beijinger person) { this.person = person; }
};
class highShanghaier {
Shanghaier person; //聚合代替繼承
public void desc() { person.desc();System.out.println (" 是高個(gè)人"); }
public highShanghaier (Shanghaier person) { this.person = person; }
};
分析2:當(dāng)一個(gè)變量的聲明類型都是某個(gè)基類(Person)的子類(Beijinger,Shanghaier)的時(shí)候,就該將它聲明為這個(gè)基類(Person),由于多態(tài),可以使得它在未來(lái)(運(yùn)行時(shí))成為子類的對(duì)象。當(dāng)把以上代碼中的類Beijinger和Shanghaier都替換為Person后,發(fā)現(xiàn)這兩個(gè)類除了類名之外都相同,所以可以合并,變?yōu)椋?/p>
class highPerson{
Person person; //用基類代替子類
public void desc() { person.desc();System.out.println (" 是高個(gè)人"); }
public highPerson(Person person) { this.person = person; }
};
分析3:擴(kuò)展時(shí)需要限制這個(gè)highPerson類實(shí)現(xiàn)抽象接口函數(shù)public void desc(),為了保證從繼承轉(zhuǎn)為組合/聚合后的函數(shù)public void desc()仍然遵循接口規(guī)范,還是需要通過(guò)繼承來(lái)完善接口規(guī)范,不過(guò)只需要繼承基類Person。繼續(xù)對(duì)highPerson類作如下修改:
class highPerson extends Person //為實(shí)現(xiàn)接口public void desc()繼承基類Person
分析4:這里,highPerson、richPerson和highrichPerson三個(gè)類中都含有字段Person person。根據(jù)重構(gòu)原則,當(dāng)多個(gè)類中含有重復(fù)字段和方法,應(yīng)該將其提到基類中去。但是,如果將Person person提到Person基類中去,會(huì)發(fā)現(xiàn)這是不合理的。為解決這個(gè)問(wèn)題,這里設(shè)計(jì)一個(gè)中間類DecoratorPerson。
abstract class DecoratorPerson extends Person{ //中間類
Person person; //以聚合的方式來(lái)支持未來(lái)多態(tài)的變化
public DecoratorPerson(Person person) { this.person = person; }
};
這樣,人的特性類就變?yōu)椋?/p>
class highPerson extends DecoratorPerson{
public void desc() { person.desc();System.out.println(" 是高個(gè)人"); }
public highPerson(Person person) { super(person); }
};
客戶端調(diào)用:
Beijinger p=new Beijinger(); p.setName("Zhangsan");
highPerson hc=new highPerson(p); hc.desc();
richPerson rc=new richPerson(p); rc.desc();
分析5:這里,類richPerson和highPerson都繼承自Person,并持有Person類的成員,所以就可以用一個(gè)highPerson對(duì)象初始化richPerson對(duì)象的Person成員,語(yǔ)句如下:
richPerson rp=new richPerson(hc); rp.desc();
這樣,不需要組合特性highrichPerson類也可以描述組合特性,就可以刪除組合特性類,僅保留單個(gè)特性。設(shè)n是地區(qū)的個(gè)數(shù),m是特性個(gè)數(shù),則需要的類的最終個(gè)數(shù)是:1+n+1+m<1+n*2m,開(kāi)始時(shí)的n=2、m=2(高、富),所以需要的類是1+2+1+2=6個(gè)。此時(shí),無(wú)論是增加地區(qū)還是增加特性,只需再增加一個(gè)類。重構(gòu)后增加Handsome特性的結(jié)構(gòu)圖如圖2所示。
由這個(gè)實(shí)例的結(jié)構(gòu)圖自然就引出了裝飾設(shè)計(jì)模式的結(jié)構(gòu)圖,此處不贅述。
2.3? 要點(diǎn)
裝飾設(shè)計(jì)模式里的繼承是為了接口的規(guī)范,組合/聚合是為了將來(lái)支持具體實(shí)現(xiàn)類、充分利用多態(tài)性消除沒(méi)必要的派生類。既繼承又組合/聚合是裝飾設(shè)計(jì)模式的特色。裝飾設(shè)計(jì)模式通過(guò)采用組合/聚合而不僅僅是繼承的手法根據(jù)需要向多個(gè)方向擴(kuò)展相互獨(dú)立的功能,在運(yùn)行時(shí)動(dòng)態(tài)裝配這些功能,實(shí)現(xiàn)比定義組合類更靈活的不同功能的組合,這一過(guò)程避免了使用繼承帶來(lái)的靈活性差和功能擴(kuò)展時(shí)的子類爆炸問(wèn)題。
3? 結(jié)? 論
裝飾設(shè)計(jì)模式的上述教學(xué)過(guò)程已經(jīng)應(yīng)用到我校計(jì)算機(jī)專業(yè)軟件設(shè)計(jì)模式課程教學(xué)中,學(xué)生反映良好。軟件設(shè)計(jì)模式是設(shè)計(jì)方面的模板,它不是憑空想象出來(lái)的,而是實(shí)踐中的經(jīng)驗(yàn)總結(jié),老師要向?qū)W生傳授軟件設(shè)計(jì)模式的形成過(guò)程。本文以裝飾設(shè)計(jì)模式為例介紹了它的設(shè)計(jì)動(dòng)機(jī),通過(guò)具體實(shí)例的一般實(shí)現(xiàn)及其改進(jìn)思路,經(jīng)過(guò)分析重構(gòu),使學(xué)生自然得出裝飾設(shè)計(jì)模式,引導(dǎo)學(xué)生發(fā)現(xiàn)其要點(diǎn),這樣才能更深入地理解,并把理論思想融合在系統(tǒng)架構(gòu)中。
參考文獻(xiàn):
[1] 溫立輝.軟件設(shè)計(jì)模式分析 [J].科技創(chuàng)新與應(yīng)用,2020(7):92-93.
[2] GAMMA E,HELM R,JOHNSON R,et al.Design Patterns:Elements of Reusable Object-Oriented Software [M]. New Jersey USA:Addison-Wesley Publishing Company,1995.
[3] 肖力,周斌.推進(jìn)信息化教學(xué) 打造精彩教學(xué)設(shè)計(jì) [J].物理教師,2020,41(2):25-29+32.
[4] 楊承清,呂耀平,戴慶敏,等.基于直觀認(rèn)知的《園林設(shè)計(jì)初步》過(guò)程性教學(xué)改革探析 [J].西南師范大學(xué)學(xué)報(bào)(自然科學(xué)版),2019,44(11):161-166.
[5] 紀(jì)程宇,朱雪峰.設(shè)計(jì)模式組合操作優(yōu)化研究 [J].計(jì)算機(jī)科學(xué),2020,47(3):19-24.
作者簡(jiǎn)介:朱紅梅(1969.12—),女,漢族,上海崇明人,副
教授,博士,研究方向:知識(shí)工程、智能信息處理;王魯(1981. 11—),男,漢族,山東泰安人,副教授,博士,研究方向:智能信息處理。