裝飾模式(Decorator)

一、概念ide

裝飾模式動態地給一個對象添加一些額外的職責。就擴展功能而言,它比生成子類方式更爲靈活,屬於結構性模式一種。
學習

二、模式結構this

  • 抽象組件角色(Component):定義一個對象接口,以規範準備接受附加責任的對象,便可以給這些對象動態地添加職責。
  • 具體組件角色(ConcreteComponent) :被裝飾者,定義一個將要被裝飾增長功能的類。能夠給這個類的對象添加一些職責。
  • 抽象裝飾器(Decorator):維持一個指向構件Component對象的實例,並定義一個與抽象組件角色Component接口一致的接口。
  • 具體裝飾器角色(ConcreteDecorator):向組件添加職責。

三、使用場景調試

  • 在不影響其餘對象的狀況下,以動態、透明的方式給單個對象添加職責
  • 須要動態地給一個對象增長功能,這些功能也能夠動態地被撤銷
  • 當不能採用繼承的方式對系統進行擴充或者採用繼承不利於系統擴展和維護時。不能採用繼承的狀況主要有兩類:第一類是系統中存在大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增加;第二類是由於類定義不能繼承(如final類)

四、優缺點code

優勢:cdn

  • 裝飾模式能夠提供比繼承更多的靈活性
  • 經過配置文件能夠在運行時選擇不一樣的裝飾器,從而實現不一樣的行爲
  • 使用不一樣的具體裝飾類以及這些裝飾類的排列組合,能夠創造出不少不一樣行爲的組合
  • 具體構件類與具體裝飾類能夠獨立變化,原有代碼無須改變,符合「開閉原則」

缺點:對象

  • 裝飾類和小對象的產生將增長系統的複雜度,加大學習與理解的難度
  • 屢次裝飾的對象,調試時尋找錯誤可能須要逐級排查,較爲煩瑣

五、實例繼承

在購買奶茶的時候,常常會有選擇配料的選項,每種配料的價格不同,能夠多種組合,價格也不同。首先先定義奶茶的接口,具備名稱和價格方法接口

public interface IMilkTea {

    String name();

    double price();
}

繼承IMilkTea的相關茶類class

public class RedTea implements IMilkTea {

    @Override
    public String name() {
        return "紅茶";
    }

    @Override
    public double price() {
        return 10;
    }
}
public class GreenTea implements IMilkTea {

    @Override
    public String name() {
        return "綠茶";
    }

    @Override
    public double price() {
        return 12;
    }
}

定義具體裝飾類Decorator,裝飾相關奶茶

public class Decorator implements IMilkTea {

    @Override
    public String name() {
        return null;
    }

    @Override
    public double price() {
        return 0;
    }
}

繼承Decorator的相關類

public class IceCream extends Decorator {

    private String name = "加雪糕";
    private IMilkTea milkTea;

    public IceCream(IMilkTea milkTea) {
        this.milkTea = milkTea;
    }

    @Override
    public String name() {
        return milkTea.name() + name;
    }

    @Override
    public double price() {
        return milkTea.price() + 3;
    }
}
public class Pearl extends Decorator {
    private String name = "加珍珠";
    private IMilkTea milkTea;

    public Pearl(IMilkTea milkTea) {
        this.milkTea = milkTea;
    }

    @Override
    public String name() {
        return milkTea.name() + name;
    }

    @Override
    public double price() {
        return milkTea.price() + 2;
    }
}

客戶端使用

public static void main(String[] args) {
    IMilkTea milkTea = new RedTea();
    milkTea = new IceCream(milkTea);
    milkTea = new Pearl(milkTea);
    System.out.println(milkTea.name() + "\n價格:" + milkTea.price());
}
相關文章
相關標籤/搜索