Java設(shè)計(jì)模式——裝飾者模式
我們來(lái)看一個(gè)圖片

圖片上面很清楚的顯示了我們裝飾者模式中的一些結(jié)構(gòu),那么我就來(lái)給大家分析一下:
1、Component是抽象構(gòu)建,什么意思呢,它是一個(gè)借口或者是抽象類,就是定義我們最核心的對(duì)象,也就是最原始的對(duì)象。
但是我們要注意
在裝飾模式中,必然有一個(gè)最基本、最核心、最原始的接口或抽象類充當(dāng)Component抽象構(gòu)件。
2、ConcreteComponent 具體構(gòu)件也就是說(shuō)ConcreteComponent是最核心、最原始、最基本的接口或抽象類的實(shí)現(xiàn),你要裝飾的就是它。
3、Decorator裝飾角色 一般是一個(gè)抽象類,做什么用呢?實(shí)現(xiàn)接口或者抽象方法,它里面可不一定有抽象的方法呀,在它的屬性里必然有一個(gè)private變量指向Component抽象構(gòu)件。
4、具體裝飾角色 什么意思呢,就是我們可以在這些類中具體的寫入方法。ConcreteDecoratorA和ConcreteDecoratorB是兩個(gè)具體的裝飾類,你要把你最核心的、最原始的、最基本的東西裝飾成其他東西。
定義差不多就講到這里了,那么接下來(lái)我們就開(kāi)始講例子
我們考試的時(shí)候我一般都是靠40多名的,而全班也只有40多名,那我們考試考完后,還要讓家長(zhǎng)簽字。這可愁壞我了,不過(guò)還好機(jī)智的我想出了個(gè)辦法,就是先說(shuō)我們的最高成績(jī),也沒(méi)比我高多少,然后在老爸看完成績(jī)單后,告訴他我在全班排第38名,這個(gè)也是實(shí)情,為啥呢?有將近十個(gè)同學(xué)退學(xué)了!這個(gè)情況我是不會(huì)說(shuō)的。不知道是不是當(dāng)時(shí)第一次發(fā)成績(jī)單時(shí)學(xué)校沒(méi)有考慮清楚,沒(méi)有寫上總共有多少同學(xué),排第幾名,反正是被我鉆了個(gè)空子。
我們來(lái)看看這個(gè)圖

圖上面寫了一個(gè)成績(jī)單的抽象類,我們可以按照前面一張圖的分析來(lái)看,
1、首先我們定義了一個(gè)抽象類SchoolReport.class
public abstract class SchoolReprt {
//成績(jī)單主要展示的就是你的成績(jī)情況
public abstract void report();
//成績(jī)單要家長(zhǎng)簽字,這是最要命的
public abstract void sign(String name);
}
2、然后我們定義了一個(gè)四年級(jí)的成績(jī)單FouthGradeSchoolReport 集成SchoolReport類,這個(gè)類是具體的實(shí)現(xiàn)類
public class FouthGradeSchoolReport extends SchoolReprt {
//成績(jī)單
@Override
public void report() {
// TODO Auto-generated method stub
System.out.println("尊敬的XXX家長(zhǎng):");
System.out.println("........");
System.out.println("語(yǔ)文: 62 數(shù)學(xué):65 體育:98 自然:63");
System.out.println("。。。。。。。。");
System.out.println("家長(zhǎng)簽字:");
}
//家長(zhǎng)簽名
public void sign(String name) {
// TODO Auto-generated method stub
System.out.println("家長(zhǎng)簽名:" +name );
}
}
3、我們可以寫Decorator類來(lái)繼承SchoolReport 類,這些類就是用來(lái)修飾SchoolReport類的方法
public abstract class Decorator extends SchoolReprt {
//首先我要知道是哪個(gè)成績(jī)單
private SchoolReprt sr;
//構(gòu)造函數(shù),傳遞成績(jī)單過(guò)來(lái)
public Decorator(SchoolReprt sr){
this.sr = sr;
}
//成績(jī)單還是要被看到的
@Override
public void report() {
// TODO Auto-generated method stub
this.sr.report();
}
//看完還是要簽名的
@Override
public void sign(String name) {
// TODO Auto-generated method stub
this.sr.sign(name);
}
}
4、我們用多個(gè)類來(lái)修飾具體的角色
public class HighSCoreDecorator extends Decorator{
//構(gòu)造函數(shù)
public HighSCoreDecorator(SchoolReprt sr) {
super(sr);
// TODO Auto-generated constructor stub
}
//我要匯報(bào)最高成績(jī)
private void reportHighScore(){
System.out.println("這次考試語(yǔ)文最高是75,數(shù)學(xué)是78,自然是80");
}
//我要在老爸看成績(jī)單前告訴他最高成績(jī),否則等他一看,就掄起掃帚揍我,我哪里還有機(jī)會(huì)說(shuō)啊
@Override
public void report() {
// TODO Auto-generated method stub
this.reportHighScore();
super.report();
}
}
public class SortDecorator extends Decorator{
//構(gòu)造函數(shù)
public SortDecorator(SchoolReprt sr) {
super(sr);
// TODO Auto-generated constructor stub
}
//告訴老爸學(xué)校的排名情況
private void reportSort(){
System.out.println("我的排名是38名");
}
//老爸看完成績(jī)單后再告訴他,加強(qiáng)作用
@Override
public void report() {
// TODO Auto-generated method stub
super.report();
this.reportSort();
}
}
最后,我們開(kāi)始實(shí)現(xiàn)我們的Father ,也就是主方法
public class Father {
public static void main(String[] args) {
//把成績(jī)單拿過(guò)來(lái)
SchoolReprt sr;
//原裝的成績(jī)單
sr = new FouthGradeSchoolReport();
//加了最高分說(shuō)明的成績(jī)單
sr = new HighSCoreDecorator(sr);
//又加了成績(jī)排名的說(shuō)明
sr = new SortDecorator(sr);
//看成績(jī)單
sr.report();
//然后老爸一看,很開(kāi)心,就簽名了
sr.sign("你爹");
}
}
運(yùn)行結(jié)果就是:
這次考試語(yǔ)文最高是75,數(shù)學(xué)是78,自然是80
尊敬的XXX家長(zhǎng):
........
語(yǔ)文: 62 數(shù)學(xué):65 體育:98 自然:63
。。。。。。。。
家長(zhǎng)簽字:
我的排名是38名
家長(zhǎng)簽名:你爹
那我們來(lái)分析一下,這個(gè)裝飾類的用法
優(yōu)點(diǎn):
● 裝飾類和被裝飾類可以獨(dú)立發(fā)展,而不會(huì)相互耦合。換句話說(shuō),Component類無(wú)須知
道Decorator類,Decorator類是從外部來(lái)擴(kuò)展Component類的功能,而Decorator也不用知道具
體的構(gòu)件。
● 裝飾模式是繼承關(guān)系的一個(gè)替代方案。我們看裝飾類Decorator,不管裝飾多少層,返
回的對(duì)象還是Component,實(shí)現(xiàn)的還是is-a的關(guān)系。
● 裝飾模式可以動(dòng)態(tài)地?cái)U(kuò)展一個(gè)實(shí)現(xiàn)類的功能,這不需要多說(shuō),裝飾模式的定義就是如此。
缺點(diǎn):
對(duì)于裝飾模式記住一點(diǎn)就足夠了:多層的裝飾是比較復(fù)雜的。為什么會(huì)復(fù)雜呢?你想想看,就像剝洋蔥一樣,你剝到了最后才發(fā)現(xiàn)是最里層的裝飾出現(xiàn)了問(wèn)題,想象一下工作量吧,因此,盡量減少裝飾類的數(shù)量,以便降低系統(tǒng)的復(fù)雜度。
使用的場(chǎng)景
● 需要擴(kuò)展一個(gè)類的功能,或給一個(gè)類增加附加功能。
● 需要?jiǎng)討B(tài)地給一個(gè)對(duì)象增加功能,這些功能可以再動(dòng)態(tài)地撤銷。
● 需要為一批的兄弟類進(jìn)行改裝或加裝功能,當(dāng)然是首選裝飾模式。