設計模式-裝飾者模式

前言

設計模式遍及咱們編碼的每個角落,例如JAVA剛入門那會作的第一個窗口程序用的Swing中的ActionsListener類就是觀察者模式實現的;以及咱們文件操做接觸比較多的java.io包內的類有許多就是裝飾者模式設計的。若是深刻研究過Spring源碼的人都會有這個感慨:Spring就是一些設計模式狂魔的做品java

設計模式有一個很是重要的面向對象原則:針對接口編程,不針對實現編程。 在咱們debug排查故障或在寫程序的時候多多少少都會有看過Spring MVC中的一些源碼,大多數人都會發現Spring的代碼是比較難看懂的。那是由於咱們大多都在用面向實現編程的思惟去思考代碼。這樣去看一羣設計模式狂魔整出來的東西固然是有至關大的難度的。咱們須要看懂讀懂Spring源碼,或者其餘開源代碼必備的一個良好的功底那就是要熟悉常見的設計模式。編程

裝飾者模式

什麼是裝飾者模式?咱們來看看度孃的解讀設計模式

動態的將責任附加到對象上。若要擴展功能,裝飾者提供了有別於繼承的另外一種選擇bash

咱們先從咱們所熟悉的java.io包內的裝飾者模式實現的類入手。咱們來看一個熟悉的對象集合 測試

BufferedInputStreamLinerNumberInputStream都是擴展自 FilterInputStream,而 FilterInputStream是一個抽象的裝飾類。

裝飾java.io類

咱們從上邊的java.io類中分析確認了裝飾者的重要用途:動態的將責任附加到對象上。ui

爲何要使用裝飾者模式

咱們從設計一個簡單飲料店提及,飲料店中有原味奶茶,珍珠奶茶,綠茶,抹茶等;調料有糖,牛奶,奶泡等。咱們會在第一時間在腦中進行一次類圖分析。this

這種設計相似硬編碼形式在後期並不能作很好的擴展,並違背了一個很是重要的面向對象設計原則: 類應該對擴展開放,對修改關閉

咱們能夠看出這種經過繼承設計的飲料店是有很大的缺陷:調料價錢出現改變是會使咱們更改現有的代碼;一但出現新的調料或開發出新的飲料都需對現有代碼做比較大的改動。這樣的代碼可維護性是很是糟糕的。編碼

接着咱們用裝飾者模式作一次的從新設計 spa

當咱們組件與裝飾者模式組合時,就是再加入新的行爲。例如紅豆+珍珠=紅豆珍珠奶茶,新的茶飲出來了,無需在添加一個新的類。debug

代碼實現

飲料抽象類

public abstract class Berverage {//飲料店抽象基類
    public String description;
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public abstract int Cost();
}
複製代碼

調料抽象類

public abstract class CondimentDecorator  extends  Berverage{
    public abstract String getDescription();
}
複製代碼

飲料類

public class GreenTea extends Berverage {

    public GreenTea () {
        description = "this is a cup of green tea ";
    }

    public int Cost() {
        return 5;
    }
}
public class MilkTea extends  Berverage {
    public MilkTea() {
        description = "this is a cup of milk tea";
    }
    public int Cost() {
        return 6;
    }
}

public class PearlsMilkTea extends Berverage {
    public PearlsMilkTea() {
        description = "this is a cup of pearls milk tea ";
    }
    public int Cost() {
        return 2;
    }
}

複製代碼

調料類

public class Milk extends CondimentDecorator {//牛奶
    Berverage berverage;
    public Milk( Berverage berverage) {
        this.berverage = berverage;
    }

    public String getDescription() {
        return berverage.getDescription()+"+milk";
    }

    public int Cost() {
        return berverage.Cost()+3;
    }
}

複製代碼

測試代碼

public class Application {

    public static void main(String[] args) {

        //珍珠奶茶
        Berverage berverage1 = new PearlsMilkTea();
        System.out.println(berverage1.getDescription() + " cost = " + berverage1.Cost());

        //綠茶加牛奶
        Berverage berverage = new GreenTea();
        berverage = new Milk(berverage);
        System.out.println(berverage.getDescription()+"cost = "+berverage.Cost());
    }
}
複製代碼

測試結果

點題

裝飾者模式:動態的將責任附加到對象上。若要擴展功能,裝飾者提供了有別於繼承的另外一種選擇

篇幅中講到了兩個重要的面向對象設計原則

  • 針對接口編程,不針對實現編程
  • 類應該對擴展開放,對修改關閉

The last

三人行,必有我師。在給你們分享乾貨的同時,才疏學淺還望你們大刀予以斧正。也歡迎關注個人掘金或簡書,名稱爲柴碼

相關文章
相關標籤/搜索