大話設計模式筆記(四)の裝飾模式

舉個栗子

問題描述

能夠給人搭配嘻哈服或白領裝的程序。ide

簡單實現

代碼

/**
 * 人類
 * Created by callmeDevil on 2019/6/23.
 */
public class Person {

    private String name;

    public Person(String name) {
        this.name = name;
    }

    public void wearTShirts(){
        System.out.print("大T恤 ");
    }

    public void wearBigTrouser(){
        System.out.print("垮褲 ");
    }

    public void wearSneakers(){
        System.out.print("破球鞋 ");
    }

    public void wearSuit(){
        System.out.print("西裝 ");
    }

    public void wearTie(){
        System.out.print("領帶 ");
    }

    public void wearLeatherShoes(){
        System.out.print("皮鞋 ");
    }

    public void show(){
        System.out.println("裝扮的" + name);
    }

}
/**
 * 裝扮測試類
 * Created by callmeDevil on 2019/6/23.
 */
public class Test {

    public static void main(String[] args) {
        Person devil = new Person("Devil");

        System.out.println("第一種裝扮:");
        devil.wearTShirts();
        devil.wearBigTrouser();
        devil.wearSneakers();
        devil.show();

        System.out.println("\n第二種裝扮:");
        devil.wearSuit();
        devil.wearTie();
        devil.wearLeatherShoes();
        devil.show();
    }

}

測試結果

第一種裝扮:
大T恤 垮褲 破球鞋 裝扮的Devil

第二種裝扮:
西裝 領帶 皮鞋 裝扮的Devil

存在缺陷

若是須要增長「超人」裝扮,會致使須要修改「Person」類,違背了開放-封閉原則測試

簡單實現進化版

代碼

/**
 * 人類
 * Created by callmeDevil on 2019/6/23.
 */
public class Person {
    
    private String name;

    public Person(String name){
        this.name = name;
    }

    public void show(){
        System.out.print("裝扮的" + name);
    }

}
/**
 * 服裝抽象類
 * Created by callmeDevil on 2019/6/23.
 */
public abstract class Finery {
    
    public abstract void show();
    
}
/**
 * T恤 類
 * Created by callmeDevil on 2019/6/23.
 */
public class TShirts extends Finery {
    
    @Override
    public void show() {
        System.out.print("大T恤 ");
    }
    
}
/**
 * 垮褲 類
 * Created by callmeDevil on 2019/6/23.
 */
public class BigTrouser extends Finery {

    @Override
    public void show() {
        System.out.print("垮褲 ");
    }

}

// 其他子類類似,此處省略
/**
 * 裝飾升級版測試
 * Created by callmeDevil on 2019/6/23.
 */
public class Test {

    public static void main(String[] args) {
        Person devil = new Person("Devil");

        System.out.println("第一種裝扮:");
        Finery tShirts = new TShirts();
        Finery bigTrouser = new BigTrouser();
        Finery sneakers = new Sneakers();
        tShirts.show();
        bigTrouser.show();
        sneakers.show();
        devil.show();

        System.out.println("\n第二種裝扮:");
        Finery suit = new Suit();
        Finery tie = new Tie();
        Finery leatherShoes = new LeatherShoes();
        suit.show();
        tie.show();
        leatherShoes.show();
        devil.show();
    }

}

測試結果

第一種裝扮:
大T恤 垮褲 破球鞋  裝扮的Devil

第二種裝扮:
西裝 領帶 皮鞋 裝扮的Devil

存在問題

如今若是要加超人裝扮,只要增長子類就能夠了,可是這麼作雖然把「服裝」類和「人」類分離開了,仍然是存在問題的。把「大T恤」、「垮褲」、「破球鞋」和「裝扮的Devil」一個詞一個詞顯示出來,就比如:你光着身子,當着你們的面,先穿T恤,再穿褲子,再穿鞋,彷彿在跳穿衣舞。。。所以須要一個房間(組合類)來換衣服,同時這個穿的順序對每一個人來講是不固定的,有的人喜歡先穿褲子,再穿鞋,最後穿T恤。。只須要把所需的功能按正確的順序串聯起來進行控制便可。ui

裝飾模式

定義

動態地給一個對象添加一些額外的職責,就增長來講,裝飾模式比生成子類更爲靈活this

UML圖

  • Component是定義一個對象接口,能夠給這些對象動態地添加職責。
  • ConcreteComponent是定義了一個具體的對象,也能夠給這個對象添加一些職責。
  • Decorator,裝飾抽象類,繼承了Component,從外類來擴展Component類功能,但對於Component來講,是無需知道Decorator的存在的。
  • 至於ConcreteDecorator就是具體的裝飾對象,起到了給Component添加職責的功能。

簡單實現究極進化->裝飾模式實現

代碼

/**
 * 究極進化人類(ConcreteComponent)
 * Created by callmeDevil on 2019/6/23.
 */
public class Person {

    private String name;

    public Person(){}

    public Person(String name){
        this.name = name;
    }

    public void show(){
        System.out.println("裝扮的" + name);
    }

}
/**
 * 究極進化 服飾類(Decorator)
 * Created by callmeDevil on 2019/6/23.
 */
public abstract class Finery extends Person{

    protected Person component;

    /**
     * 裝扮
     * @param component
     */
    public void decorate(Person component) {
        this.component = component;
    }

    @Override
    public void show() {
        if (component != null) {
            component.show();
        }
    }

}
/**
 * 究極進化 T恤(ConcreteDecorator)
 * Created by callmeDevil on 2019/6/23.
 */
public class TShirts extends Finery{

    @Override
    public void show() {
        System.out.print("大T恤 ");
        super.show();
    }

}
/**
 * 究極進化 垮褲(ConcreteDecorator)
 * Created by callmeDevil on 2019/6/23.
 */
public class BigTrouser extends Finery {

    @Override
    public void show() {
        System.out.print("垮褲 ");
        super.show();
    }

}

// 其他子類類似,此處省略
/**
 * 裝飾模式測試
 * Created by callmeDevil on 2019/6/23.
 */
public class Test {

    public static void main(String[] args) {
        Person devil = new Person("Devil");

        System.out.println("第一種裝扮:");
        Sneakers sneakers = new Sneakers();
        BigTrouser bigTrouser = new BigTrouser();
        TShirts tShirts = new TShirts();
        // 裝飾
        sneakers.decorate(devil);
        bigTrouser.decorate(sneakers);
        tShirts.decorate(bigTrouser);
        tShirts.show();

        System.out.println("\n第二種裝扮:");
        LeatherShoes leatherShoes = new LeatherShoes();
        Tie tie = new Tie();
        Suit suit = new Suit();
        // 裝飾
        leatherShoes.decorate(devil);
        tie.decorate(leatherShoes);
        suit.decorate(tie);
        suit.show();
    }

}

測試結果

第一種裝扮:
大T恤 垮褲 破球鞋  裝扮的Devil

第二種裝扮:
西裝 領帶 皮鞋 裝扮的Devil

總結

  • 裝飾模式是利用setComponent來對對象進行包裝的,這樣每一個裝飾對象的實現就和如何使用這個對象分離開了,每一個裝飾對象只關心本身的功能,不須要關心如何被添加到對象鏈當中。
  • 若是隻有一個ConcreteComponent類而沒有抽象的Component類,那麼Decorator類能夠是ConcreteComponent的一個子類。一樣道理,若是隻有一個ConcreteDecorator類,那麼就沒有必要創建一個單獨的Decorator類,而能夠把DecoratorConcreteDecorator的責任合併成一個類。
  • 裝飾模式是爲已有功能動態地添加更多功能的一種方式
  • 不使用裝飾模式,且系統須要新功能的時候,是向舊的類中添加新的代碼,這些新加的代碼一般裝飾了原有類的核心職責或主要行爲。在主類中加入了新的字段、方法和邏輯,會增長主類的複雜度,而這些新加入的東西僅僅是爲了知足一些只在某種特定狀況下才會執行的特殊需求。裝飾模式提供了很是好的解決方案,它把每一個要裝飾的功能放在單獨的類中,並讓這個類包裝它所要裝飾的對象,所以,當須要執行特殊行爲時,客戶代碼就能夠在運行時根據須要有選擇地、按順序地使用裝飾功能包裝對象。
  • 裝飾模式的優勢是把類中裝飾功能從類中搬移去除,這樣能夠簡化原有的類。這麼作最大的好處就是有效地把類的核心職責和裝飾功能區分開了,並且能夠去除相關類中重複的裝飾邏輯。
相關文章
相關標籤/搜索