1. 程式人生 > >裝飾模式——Decorator

裝飾模式——Decorator

案例展示——Decorator怎麼用?

 現在有這樣一種場景:關於二手車我們都不會陌生,或多或少我們都會有接觸。那你有沒有想過,如何才能把一輛二手車賣出好的價錢呢?是直接和買主攤牌二手車的所有效能引數,還是會適當的加以修飾一下來獲得一個好的價位呢?誠然,所謂商場之道,誠信至上,我們當然需要誠實的與買主說清楚二手車的各種引數,但是在商言商,我想些許修飾也是不過分的,下面是一家二手車4S店賣二手車的一個類圖設計:

image

類圖元素分析:

  • SHCar:二手車抽象類,裡面有兩個基本的方法,show()方法用於向用戶展示二手車的基本引數;order()方法為使用者下訂單。

  • SHBaomaCar:具體的二手車型別

  • Decorator:一個抽象的裝飾類,它會對每輛二手車進行裝飾

  • PowerEngineDecorator:具體的裝飾類,繼承了Decorator,用於裝飾二手車的引擎

  • FastSpeedDecorator:具體的裝飾類,繼承了Decorator,用於裝飾二手車的速度

下面是具體的程式碼展示:

// 抽象車類
public abstract class SHCar {
    // 給客戶展示二手車的基本資訊
    public abstract void show();
    // 使用者下訂單
    public abstract void order(String name);
} // 具體的型別 public class SHBaomaCar extends SHCar{ // 展示一下二手寶馬車 public void show() { System.out.println("型號:寶馬X6"); System.out.println("顏色:寶石藍"); System.out.println("發動機:動力好"); System.out.println("推薦:價效比高,值得擁有"); } // 使用者下訂單 public void order(String name)
{ System.out.println("我是 " + name + ",這輛車我要了!"); } } // 抽象裝飾器 public abstract class Decorator extends SHCar{ // 那種型別的二手車:寶馬,賓士,奧迪,法拉利.... private SHCar sc; // 建構函式,傳入二手車 public Decorator(SHCar sc) { this.sc = sc; } // 檢視二手車的具體資訊 public void show() { this.sc.show(); } // 使用者下訂單 public void order(String name) { this.sc.order(name); } } // 引擎裝飾器 public class PowerEngineDecorator extends Decorator{ // 建構函式 public PowerEngineDecorator(SHCar sc) { super(sc); } // 說說這輛車的強大的引擎 private void showEngine() { System.out.println("====進口引擎,動力杆杆的!!!===="); } // 在向用戶展示之前先給他說一下 @Override public void show() { this.showEngine(); super.show(); } } // 速度裝飾器 public class FastSpeedDecorator extends Decorator { // 建構函式 public FastSpeedDecorator(SHCar sc) { super(sc); } // 說說這輛車的速度:百米加速3秒! private void showSpeed() { System.out.println("=====百米加速3秒!!!====="); } // 在展示之後和使用者說一下,增加吸引力 @Override public void show() { super.show(); this.showSpeed(); } } // 客戶買車 public class Client { public static void main(String[] args) { // 沒有修飾的原裝車 SHCar sc = new SHBaomaCar(); // 修飾一下:強大的引擎 sc = new PowerEngineDecorator(sc); // 強調一下:超快的速度 sc = new FastSpeedDecorator(sc); // 展示 sc.show(); // 使用者很開心,下單! sc.order("張三"); } } // 執行結果如下: ====進口引擎,動力杆杆的!!!==== 型號:寶馬X6 顏色:寶石藍 發動機:動力好 推薦:價效比高,值得擁有 =====百米加速3秒!!!===== 我是 張三,這輛車我要了!

 上面的例子中使用的就是裝飾模式,通過一個抽象的裝飾器得到它要裝飾的型別,然後交給具體的裝飾型別去裝飾,這樣在沒有改變二手車基本引數的情況下,使其給客戶的觀感更好,人家自然很高興就下單了。

深入分析——Decorator是什麼?

Decorator的定義

定義: 動態的給一個物件新增一些額外的職責,就增加功能來說,裝飾模式比生成子類更加靈活。下面是裝飾模式的通用類圖:

image

  • Conponent組建:一個介面或者抽象類,定義最核心的物件,如二手車

  • ConcreateComponent組建:具體的構建,被裝飾的物件

  • Decorator組建:裝飾者

  • ConcreateDecorator:具體的裝飾者

下面是具體程式碼

// 抽象構建
public abstract class Component {
    // 抽象方法
    public abstract void operate();
}

// 具體構建
public class ConcreateComponent extends Component {
    // 具體實現
    public void operate() {
        // 業務邏輯
    }
}

// 抽象裝飾器
public abstract class Decorator extends Component{
    // 修飾哪個組建
    private Component component = null;
    // 通過建構函式傳遞被修飾者
    public Decorator(Component component) {
        this.component = component;
    }
    // 委託給被修飾者執行
    @Override
    public void operate() {
        this.component.operate();
    }
}

// 具體的裝飾器
public class ConcreateDecorator1 extends Decorator {
    // 傳遞被修飾者
    public ConcreateDecorator1(Component component) {
        super(component);
    }
    // 定義自己的修飾方法
    private void method1() {
        // 修飾
    }
    // 重寫父類的operate()方法
    public void operate() {
        this.method1();
        super.operate();
    }
}

// 具體的裝飾器
public class ConcreateDecorator2 extends Decorator {
    // 傳遞被修飾者
    public ConcreateDecorator2(Component component) {
        super(component);
    }
    // 定義自己的修飾方法
    private void method2() {
        // 修飾
    }
    // 重寫父類的operate()方法
    public void operate() {
        super.operate();
        this.method2();
    }
}

// 場景類
public class Client {
    public static void main(String[] args) {
        Component component = new ConcreateComponent();
        // 第一次修飾
        component = new ConcreateDecorator1(component);
        // 第二次修飾
        component = new ConcreateDecorator2(component);
        // 執行
        component.operate();
    }
}
Decorator的優點
  • 裝飾類和被裝飾類可以獨立發展,而不會相互耦合

  • 裝飾模式是繼承關係的一個替代方案

  • 裝飾模式可以動態的擴充套件一個實現類的功能

Decorator的缺點
  • 裝飾類太多會增加複雜性

  • 會產生很多小物件,增加系統的複雜性

  • 雖然比繼承更加靈活,當時也意味著比繼承更加容易出錯。在出現錯誤後,由於多層裝飾,排錯很困難,需要逐級排查,較為繁瑣

Decorator的應用場景

  • 需要擴張一個類的功能或給一個類增加附加功能

  • 需要動態的給一個物件增加功能,這些功能可以再動態的撤銷

  • 需要為一批兄弟類改裝或加裝功能

參考

《設計模式之禪》