国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

開發(fā)之路(設(shè)計模式三:裝飾者模式)

Vicky / 1399人閱讀

摘要:若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。裝飾者模式意味著一群裝飾者類,這些類用來包裝具體組件。裝飾者類反映出被裝飾組件類型。裝飾者會導(dǎo)致設(shè)計中出現(xiàn)許多小對象,如果過度使用,會讓程序變得很復(fù)雜。

嘿嘿嘿,你是不是很喜歡用繼承呢?感覺沒什么事情是一個“爸爸”類搞不定的,有的話就兩個,快來跟我看看這個模式吧,它能讓你“斷奶”,給愛用繼承的人一個全新的設(shè)計眼界。

直奔主題,你是否有聽說過組合呢?你是否覺得繼承往往有的時候沒你想象的那么好用呢?如果有,你又是否嘗試自己解決這個問題呢?讓我們來看個例子~~~~

假設(shè)我們有家咖啡店,設(shè)計如下
飲料(Beverage)基類,有4個子類,分別是綜合咖啡(HouseBlend),深焙咖啡 (DarkRoast),低咖啡因咖啡 (Decaf),(Espresso)濃縮咖啡,他們都是子類,繼承了cost支付方法。

嗯,看似目前沒啥問題,假設(shè)我需要改變點需求呢?
喝咖啡可以加各種各樣調(diào)料的,例如加牛奶,豆奶,摩卡,小餅干等等,而且每種飲料根據(jù)添加的調(diào)料不同還要再加對應(yīng)的調(diào)料費用,那么這些使用繼承的話。。。。。。恐怕會出現(xiàn)以下這樣的情況。。

想想以前這樣的設(shè)計,是不是有種細(xì)思極恐的感覺。。

當(dāng)然聰明一點的會這樣設(shè)計,這里我就不自己畫了,直接貼出來圖例

其實這樣的設(shè)計也非常有問題,跟上面"類爆炸"的設(shè)計沒啥區(qū)別,父類和子類依賴性太高了,低耦合。
1:假設(shè)我在父類中添加了新的調(diào)料,那么所有子類都需要相應(yīng)修改代碼,加大了工作量。
2:在父類中改變cost方法,子類也需要跟著改變。。

總之,太濫用繼承其實是給自己挖坑,繼承往往有的時候不能設(shè)計出彈性和易擴展性的代碼。這里就要說說和繼承的“死對頭”-->組合,而裝飾者模式就充分運用了組合

設(shè)計原則一:類應(yīng)該對擴展開放,對修改關(guān)閉。
注:這個原則剛開始聽是感覺自相矛盾的,確實剛開始我也有這疑問,回過頭看看觀察者模式,通過加入新的“觀察者”就相當(dāng)于拓展開放了“主題”,而“主題”本身沒有改變代碼,對修改關(guān)閉了。不急請往下看。

依舊以咖啡店做例子
這里改變做法,以飲料為主體,然后用調(diào)料“裝飾”飲料,
打個比方:如果顧客想要摩卡和奶泡深焙咖啡,要做的是:
1:拿一個深焙咖啡(HouseBlend)對象
2:以摩卡(Mocha)對象“裝飾”它
3:以奶泡(Whip)對象“裝飾”它
4:調(diào)用cost()方法,并依賴委托將調(diào)料價錢加上去
過程流程圖如下(請多看幾遍)

裝飾者模式定義:動態(tài)的將責(zé)任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。

放出裝飾者模型的類圖(重點看)

然后下面是基于此模式下的咖啡店的類圖

是不是感覺這個設(shè)計煥然一新。
下面我要好好打造我的咖啡店了

飲料抽象類

package Beverage;
/**
 * 飲料抽象類
 * 被裝飾者類
 * @author Joy
 *
 */
public abstract class Beverage {
    //飲料名稱初始化
    String description="未知飲料";

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    //價錢方法抽象化,不需要具體實現(xiàn)
    public abstract double cost();
}

下面是四個咖啡類

package Beverage;

/**
 * 深焙咖啡 
 * 
 * @author Joy
 * 
 */
public class DarkRoast extends Beverage {
    public DarkRoast() {
        description = "深焙咖啡";
    }

    @Override
    public double cost() {
        return 0.99;
    }

}
package Beverage;

/**
 * 低咖啡因咖啡 
 * 
 * 
 * 
 */
public class Decaf extends Beverage {

    public Decaf() {
        description = "低咖啡因咖啡";
    }

    @Override
    public double cost() {
        return 1.05;
    }

}
package Beverage;
/**
 * 
 * 濃縮咖啡類
 * 
 *
 */

//繼承飲料父類,因為它是飲料一種
public class Espresso extends Beverage {
    //寫一個構(gòu)造器,將飲料名稱重定義
    public Espresso() {
        description="濃縮咖啡";
    }

    //最后計算濃縮咖啡價格,先不算調(diào)料價錢,一杯濃縮咖啡1.99
    @Override
    public double cost() {        
        return 1.99;
    }

}
    package Beverage;
/**
 * 綜合咖啡類
 * 
 *
 */
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "綜合咖啡";
    }

    @Override
    public double cost() {
        return 0.89;
    }

}

調(diào)料抽象類

package Condiment;

import Beverage.Beverage;

/**
 * 調(diào)料抽象類 裝飾者類
 * 
 * @author Joy
 * 
 */
public abstract class CondimentDecorator extends Beverage {
    // 描述
    public abstract String getDescription();

}

下面是具體調(diào)料實現(xiàn)類

package Condiment;

import Beverage.Beverage;

/**
 * 摩卡類,裝飾者
 * 
 * @author Joy
 * 
 */
// 摩卡是一個裝飾者,讓它繼承裝飾者父類
public class Mocha extends CondimentDecorator {

    // 設(shè)定飲料變量記錄飲料,也就是被裝飾者
    Beverage beverage;

    // 設(shè)置構(gòu)造器將被裝飾者(飲料)被記錄到實例變量beverage中
    // 把飲料設(shè)置構(gòu)造器參數(shù),再有構(gòu)造器將此記錄到實例變量中
    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }

    // 重寫方法,將其飲料描述加上添加的調(diào)料
    @Override
    public String getDescription() {
        return beverage.getDescription() + ",加摩卡";
    }

    // 重寫方法,將飲料價錢+調(diào)料價錢
    @Override
    public double cost() {
        return beverage.cost() + 0.2;
    }

}
package Condiment;

import Beverage.Beverage;

/**
 * 豆?jié){類,裝飾者
 * 內(nèi)容與前面摩卡一樣
 * @author Joy
 *
 */
public class Soy extends CondimentDecorator {

    Beverage beverage;
    
    public Soy(Beverage beverage) {
    this.beverage=beverage;
    }
    
    @Override
    public String getDescription() {    
        return beverage.getDescription()+",加豆?jié){";
    }

    @Override
    public double cost() {
        
        return beverage.cost()+0.15;
    }

}
package Condiment;

import Beverage.Beverage;

/**
 * 奶泡類,裝飾者 內(nèi)容與前面摩卡一樣
 * 
 * @author Joy
 * 
 */
public class Whip extends CondimentDecorator {
    Beverage beverage;

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",加奶泡";
    }

    @Override
    public double cost() {
        return beverage.cost() + 0.1;
    }

}

測試類

package TestMain;

import java.math.BigDecimal;

import Beverage.Beverage;
import Beverage.DarkRoast;
import Beverage.Espresso;
import Beverage.HouseBlend;
import Condiment.Mocha;
import Condiment.Soy;
import Condiment.Whip;

public class TestMain {
    public static void main(String[] args) {
        //要一杯濃縮咖啡,什么調(diào)料都不加
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + "	$" + beverage.cost());
        
        //要一杯深焙咖啡        
        Beverage beverage2=new DarkRoast();
        //加兩份摩卡
        beverage2=new Mocha(beverage2);
        beverage2=new Mocha(beverage2);
        //加一份奶泡
        beverage2=new Whip(beverage2);
        System.out.println(beverage2.getDescription()+"	$"+beverage2.cost());
        
        //要一杯加豆?jié){,加摩卡,加奶泡的綜合咖啡
        Beverage beverage3=new HouseBlend();
        beverage3=new Whip(beverage3);
        beverage3=new Mocha(beverage3);
        beverage3=new Soy(beverage3);
        //這里對價錢保留兩位小數(shù)四舍五入
        double money=beverage3.cost();
        BigDecimal b=new BigDecimal(money);
        double f1=b.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
        System.out.println(beverage3.getDescription()+"	$"+f1);
    }
}

效果圖:

要點:
1:繼承屬于擴展形式一種,但不見的是達(dá)到彈性設(shè)計的最佳方式,組合優(yōu)于繼承。
2:應(yīng)該允許行為可以被拓展,而無需修改現(xiàn)有的代碼。
3:裝飾者模式意味著一群裝飾者類,這些類用來包裝具體組件。
4:裝飾者類反映出被裝飾組件類型。
5:可以使用無數(shù)個裝飾者包裝一個組件。
6:裝飾者會導(dǎo)致設(shè)計中出現(xiàn)許多小對象,如果過度使用,會讓程序變得很復(fù)雜。

裝飾者模式結(jié)束,這個模式是個很有用的模式,可以說是提高代碼素養(yǎng)的關(guān)鍵一步,模擬代碼已經(jīng)全部放出,注釋也寫的比較清楚,若有不理解歡迎留言。

感謝你看到這里,裝飾者模式部分結(jié)束,本人文筆隨便,若有不足或錯誤之處望給予指點,90度彎腰~很快我會發(fā)布下一個設(shè)計模式內(nèi)容,生命不息,編程不止!

參考書籍:《Head First 設(shè)計模式》
參考網(wǎng)站:
Java中的繼承與組合:http://www.importnew.com/12907.html

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/70184.html

相關(guān)文章

  • 我的Java設(shè)計模式-代理模式

    摘要:下面總結(jié)了它倆的異同相同點都需要實現(xiàn)同一個接口或者繼承同一個抽象類,并且代理角色和裝飾角色都持有被代理角色和構(gòu)件角色的引用。 寫完上一篇之后有小伙伴問我有沒有寫過代理模式,想看看我的理解。原本我的設(shè)計模式系列是按照創(chuàng)建型-行為型-結(jié)構(gòu)型的順序?qū)懴氯サ模热恍』锇檎\心誠意了,我就大發(fā)慈悲的穿插一篇代理模式。開玩笑,題外話。 說起代理模式,就不由得想起經(jīng)紀(jì)人,說起經(jīng)紀(jì)人,就想起了...對,...

    BWrong 評論0 收藏0
  • JS設(shè)計模式--裝飾模式

    摘要:當(dāng)接口比較多,裝飾器也比較多時,可以獨立抽取一個裝飾器父類,實現(xiàn)目標(biāo)類的所有接口,再創(chuàng)建真正的裝飾器來繼承這個父類。四的實現(xiàn)方式提供了一種類似的注解的語法糖,來實現(xiàn)裝飾者模式。 歡迎關(guān)注我的公眾號睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 所謂裝飾者模式,就是動態(tài)的給類或?qū)ο笤黾勇氊?zé)的設(shè)計模式。它...

    wmui 評論0 收藏0
  • Java 設(shè)計模式裝飾模式

    摘要:裝飾者模式組成結(jié)構(gòu)抽象構(gòu)件給出抽象接口或抽象類,以規(guī)范準(zhǔn)備接收附加功能的對象。裝飾者模式圖解裝飾者模式應(yīng)用場景需要擴展一個類的功能,或給一個類添加附加職責(zé)。裝飾者對象接受所有來自客戶端的請求。參考資料設(shè)計模式 一、了解裝飾者模式 1.1 什么是裝飾者模式 裝飾者模式指的是在不必改變原類文件和使用繼承的情況下,動態(tài)地擴展一個對象的功能。它是通過創(chuàng)建一個包裝對象,也就是裝飾者來包裹真實的對...

    kumfo 評論0 收藏0
  • php設(shè)計模式

    摘要:我們今天也來做一個萬能遙控器設(shè)計模式適配器模式將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口。今天要介紹的仍然是創(chuàng)建型設(shè)計模式的一種建造者模式。設(shè)計模式的理論知識固然重要,但 計算機程序的思維邏輯 (54) - 剖析 Collections - 設(shè)計模式 上節(jié)我們提到,類 Collections 中大概有兩類功能,第一類是對容器接口對象進(jìn)行操作,第二類是返回一個容器接口對象,上節(jié)我們介紹了...

    Dionysus_go 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<