一天一個設計模式:裝飾者模式

概念:

裝飾者模式又稱爲包裝(wrapper)模式。裝飾者模式對客戶端透明的方式擴展對象的功能,是繼承關係的一個替代方案。

結構:

裝飾者模式以透明的方式給一個對象附加上更多的責任,換而言之,客戶端並不會覺得對象在裝飾前後有什麼不同,裝飾者模式可以在不使用創造更多子類的情況下,將對象的功能拓展。

結構圖:

角色分析:

抽象構件(Component)角色:給出一個抽象接口,以規範準備接受附加責任的對象。

  具體構件(ConCreteComponent)角色:定義一個將要接受附加責任的類。

  裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。

  具體裝飾(ConcreteDecorator)角色:負責給構件對象“貼上”附加的責任。

代碼:

抽象構建角色:

public interface Component {
    
    public void sampleOperation();
    
}

具體構件角色:

public class ConcreteComponent implements Component {

    @Override
    public void sampleOperation() {
        // 寫相關的業務代碼
    }

}

裝飾者角色:

public class Decorator implements Component{
    private Component component;
    
    public Decorator(Component component){
        this.component = component;
    }

    @Override
    public void sampleOperation() {
        // 委派給構件
        component.sampleOperation();
    }
    
}

具體裝飾者角色:

public class ConcreteDecoratorA extends Decorator {

    public ConcreteDecoratorA(Component component) {
        super(component);
    }
    
    @Override
    public void sampleOperation() {
     super.sampleOperation();
        // 寫相關的業務代碼
    }
}
//B組件類似

具體示例

有工人接口,我們定義了鐵匠,現在要對鐵匠進行不同的技能強化。

工人接口:

public interface Worker {

    void working();
}

鐵匠實現類:

public class Smith implements Worker {

    private String name;

    private int age;

    public Smith(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public void working() {
        System.out.println("我是一個鐵匠");
    }
}

技能實現類:

public class Skill implements Worker {
    private Worker worker;

    public Skill(Worker worker) {
        this.worker = worker;
    }

    @Override
    public void working() {
        worker.working();
    }

    //爲半透明模式做的拓展
    public void heating(){}
}

具體的技能類1:

public class Hardening extends Skill {
    public Hardening(Worker worker) {
        super(worker);
    }

    @Override
    public void working() {
        System.out.println("我在淬火");
    }
}

具體的技能類2:

public class Beat extends Skill {
    public Beat(Worker worker) {
        super(worker);
    }

    @Override
    public void working() {
        System.out.println("我在反覆地捶打");
    }
}

補充:

裝飾者模式的簡化

1.去掉接口的形式,直接繼承自要被裝飾的類即可。

2.直接使用實現接口的形式實現裝飾,而不用再額外加一層繼承關係。適用於只有一個強化關係的情況

透明度的要求:

  裝飾者模式要求程序不應該聲明需要被裝飾的實體類,而是應該聲明抽象接口。

用示例中的聲明表示就是下面這樣:

即所有的人,都是工人,鐵匠是工人,會淬火的鐵匠也是工人。

        Worker worker1 = new Smith("李鐵蛋",18);
        Worker worker2 = new Hardening(worker1);

半透明的裝飾模式:

  當發現工人接口並不能滿足所有的要求的時候,要想實現透明度要求,必須在接口中添加新方法,所以很多實現的裝飾者模式都是採取“半透明”的方式,即裝飾者類可以對接口進行拓展,同時聲明的時候,可以選擇以裝飾者類爲準。

  本例中,裝飾者類就是技能類,我們爲淬火技能類添加加熱方法

        Worker worker = new Smith("李狗蛋",18);
        Hardening smith = new Hardening(worker);
        smith.heating();

  半透明的裝飾者模式是介於裝飾者模式跟適配器模式中的,適配器模式的思路是改變接口,也可以通過改寫或新增方法實現,大多數裝飾者模式實際上都是半透明的裝飾者模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章