成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

設(shè)計(jì)模式之裝飾者模式

chuyao / 1863人閱讀

摘要:相關(guān)設(shè)計(jì)模式裝飾者模式和代理模式裝飾者模式關(guān)注再一個(gè)對(duì)象上動(dòng)態(tài)添加方法代理模式關(guān)注再對(duì)代理對(duì)象的控制訪問(wèn),可以對(duì)客戶(hù)隱藏被代理類(lèi)的信息裝飾著模式和適配器模式都叫包裝模式關(guān)于新職責(zé)適配器也可以在轉(zhuǎn)換時(shí)增加新的職責(zé),但主要目的不在此。

0x01.定義與類(lèi)型

定義:裝飾模式指的是在不必改變?cè)?lèi)文件和使用繼承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。它是通過(guò)創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來(lái)包裹真實(shí)的對(duì)象。

特點(diǎn):

裝飾對(duì)象和真實(shí)對(duì)象有相同的接口。這樣客戶(hù)端對(duì)象就能以和真實(shí)對(duì)象相同的方式和裝飾對(duì)象交互。

裝飾對(duì)象包含一個(gè)真實(shí)對(duì)象的引用(reference)

裝飾對(duì)象接受所有來(lái)自客戶(hù)端的請(qǐng)求。它把這些請(qǐng)求轉(zhuǎn)發(fā)給真實(shí)的對(duì)象。

裝飾對(duì)象可以在轉(zhuǎn)發(fā)這些請(qǐng)求以前或以后增加一些附加功能。這樣就確保了在運(yùn)行時(shí),不用修改給定對(duì)象的結(jié)構(gòu)就可以在外部增加附加的功能。在面向?qū)ο蟮脑O(shè)計(jì)中,通常是通過(guò)繼承來(lái)實(shí)現(xiàn)對(duì)給定類(lèi)的功能擴(kuò)展。

類(lèi)型:結(jié)構(gòu)型

UML類(lèi)圖

樣例實(shí)現(xiàn)

/**
* 組件類(lèi)接口
*/
public interface IComponent {
    void operation();
}

/**
* 具體組件類(lèi)的具體業(yè)務(wù)邏輯實(shí)現(xiàn)
*/
public class Component implements IComponent {
    @Override
    public void operation() {
        System.out.println("component operation!");
    }
}

/**
* 裝飾器的抽象類(lèi)
*/
public abstract class ADecorator implements IComponent {
    /**
    * 關(guān)鍵在于這個(gè)組合組件接口對(duì)象
    */
    private IComponent component;

    public ADecorator(IComponent component) {
        this.component = component;
    }

    @Override
    public void operation () {
        component.operation();
    }
}

/**
* 裝飾器具體實(shí)現(xiàn)1
*/
public class Decorator1 extends ADecorator {
    public Decorator1(IComponent component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        System.out.println("decorator1");
    }
}

/**
* 裝飾器具體實(shí)現(xiàn)2
*/
public class Decorator2 extends ADecorator {

    public Decorator2(IComponent component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        System.out.println("decorator2");
    }
}

測(cè)試與應(yīng)用類(lèi)

/**
* 應(yīng)用與測(cè)試類(lèi)
*/
public class Test {

    public static void main(String[] args) {
        //應(yīng)用類(lèi)
        IComponent component;

        //初始化
        component = new Component();

        //裝飾
        component = new Decorator1(component);
        component = new Decorator2(component);

        //具體方法的調(diào)用
        component.operation();
    }
}

輸出結(jié)果

component operation!
decorator1
decorator2

裝飾著模式中的各組件:

抽象構(gòu)件(IComponent)角色:給出一個(gè)抽象接口,以規(guī)范準(zhǔn)備接收附加責(zé)任的對(duì)象。

具體構(gòu)件(Component)角色:定義一個(gè)將要接收附加責(zé)任的類(lèi)。

裝飾(ADecorator)角色:持有一個(gè)構(gòu)件(IComponent)對(duì)象的實(shí)例,并定義一個(gè)與抽象構(gòu)件接口一致的接口。

具體裝飾(Decorator1/Decorator2)角色:負(fù)責(zé)給構(gòu)件對(duì)象“貼上”附加的責(zé)任。

0x02.使用場(chǎng)景

需要擴(kuò)展一個(gè)類(lèi)的功能,或給一個(gè)類(lèi)添加附加職責(zé)。

需要?jiǎng)討B(tài)的給一個(gè)對(duì)象添加功能,這些功能可以再動(dòng)態(tài)的撤銷(xiāo)。

需要增加由一些基本功能的排列組合而產(chǎn)生的非常大量的功能,從而使繼承關(guān)系變的不現(xiàn)實(shí)。

當(dāng)不能采用生成子類(lèi)的方法進(jìn)行擴(kuò)充時(shí)。一種情況是,可能有大量獨(dú)立的擴(kuò)展,為支持每一種組合將產(chǎn)生大量的子類(lèi),使得子類(lèi)數(shù)目呈爆炸性增長(zhǎng)。另一種情況可能是因?yàn)轭?lèi)定義被隱藏,或類(lèi)定義不能用于生成子類(lèi)。

0x03.優(yōu)點(diǎn)

Decorator模式與繼承關(guān)系的目的都是要擴(kuò)展對(duì)象的功能,但是Decorator可以提供比繼承更多的靈活性。

通過(guò)使用不同的具體裝飾類(lèi)以及這些裝飾類(lèi)的排列組合,設(shè)計(jì)師可以創(chuàng)造出很多不同行為的組合。

符合開(kāi)閉原則

0x04.缺點(diǎn)

這種比繼承更加靈活機(jī)動(dòng)的特性,也同時(shí)意味著更加多的復(fù)雜性。

裝飾模式會(huì)導(dǎo)致設(shè)計(jì)中出現(xiàn)許多小類(lèi),如果過(guò)度使用,會(huì)使程序變得很復(fù)雜。

裝飾模式是針對(duì)抽象組件(Component)類(lèi)型編程。但是,如果你要針對(duì)具體組件編程時(shí),就應(yīng)該重新思考你的應(yīng)用架構(gòu),以及裝飾者是否合適。當(dāng)然也可以改變Component接口,增加新的公開(kāi)的行為,實(shí)現(xiàn)“半透明”的裝飾者模式。在實(shí)際項(xiàng)目中要做出最佳選擇

0x05.舉例實(shí)現(xiàn)裝飾著模式
我們買(mǎi)煎餅果子可以選擇加香腸,還是加雞蛋。煎餅果子就是我們的組件類(lèi),而加雞蛋加培根則是裝飾者的具體實(shí)現(xiàn)類(lèi).

裝飾者模式Java實(shí)現(xiàn)

/**
 * 煎餅的抽象類(lèi),也就是組建類(lèi)
 */
public abstract class ABattercake {

    /**
     * 最后的描述
     * @return
     */
    protected abstract String getDesc ();

    /**
     * 總共的價(jià)格
     * @return
     */
    protected abstract int cost ();

}


/**
 * 煎餅的具體實(shí)現(xiàn)
 */
public class Battercake extends ABattercake {
    @Override
    protected String getDesc() {
        return "煎餅";
    }

    @Override
    protected int cost() {
        return 8;
    }
}

/**
 * 裝飾著的抽象類(lèi)
 */
public abstract class AbstractDecorator extends ABattercake {

    //組合的煎餅對(duì)象
    private ABattercake aBattercake;

    public AbstractDecorator(ABattercake aBattercake) {
        this.aBattercake = aBattercake;
    }

    protected abstract void doSomething();

    @Override
    protected String getDesc() {
        return aBattercake.getDesc();
    }

    @Override
    protected int cost() {
        return aBattercake.cost();
    }
}

/**
 * 裝飾者的具體實(shí)現(xiàn)
 */
public class EggDecorator extends AbstractDecorator {

    public EggDecorator(ABattercake aBattercake) {
        super(aBattercake);
    }

    @Override
    protected void doSomething() {

    }

    @Override
    protected String getDesc() {
        return super.getDesc() + " 加一個(gè)雞蛋";
    }

    @Override
    protected int cost() {
        return super.cost() + 1;
    }
}

/**
 * 裝飾者的具體實(shí)現(xiàn)
 */
public class SausageDecorator extends AbstractDecorator {

    public SausageDecorator(ABattercake aBattercake) {
        super(aBattercake);
    }

    @Override
    protected void doSomething() {

    }

    @Override
    protected String getDesc() {
        return super.getDesc() + " 加一根香腸";
    }

    @Override
    protected int cost() {
        return super.cost() + 2;
    }
}

應(yīng)用的測(cè)試類(lèi)

public class Test {

    public static void main(String[] args) {
        ABattercake aBattercake;

        aBattercake = new Battercake();
        aBattercake = new EggDecorator(aBattercake);
        aBattercake = new EggDecorator(aBattercake);
        aBattercake = new SausageDecorator(aBattercake);

        System.out.println(aBattercake.getDesc() + "銷(xiāo)售價(jià)格:" + aBattercake.cost());
    }
}

輸入結(jié)果

煎餅 加一個(gè)雞蛋 加一個(gè)雞蛋 加一根香腸銷(xiāo)售價(jià)格:12

樣例UML類(lèi)圖

注意:裝飾者最上層的類(lèi)是否使用抽象類(lèi),這個(gè)是看業(yè)務(wù)的。

0x06.相關(guān)設(shè)計(jì)模式

裝飾者模式和代理模式

裝飾者模式:關(guān)注再一個(gè)對(duì)象上動(dòng)態(tài)添加方法

代理模式:關(guān)注再對(duì)代理對(duì)象的控制訪問(wèn),可以對(duì)客戶(hù)隱藏被代理類(lèi)的信息

裝飾著模式和適配器模式

都叫包裝模式

關(guān)于新職責(zé):適配器也可以在轉(zhuǎn)換時(shí)增加新的職責(zé),但主要目的不在此。裝飾者模式主要是給被裝飾者增加新職責(zé)的。

關(guān)于原接口:適配器模式是用新接口來(lái)調(diào)用原接口,原接口對(duì)新系統(tǒng)是不可見(jiàn)或者說(shuō)不可用的。裝飾者模式原封不動(dòng)的使用原接口,系統(tǒng)對(duì)裝飾的對(duì)象也通過(guò)原接口來(lái)完成使用。(增加新接口的裝飾者模式可以認(rèn)為是其變種--“半透明”裝飾者)

關(guān)于其包裹的對(duì)象:適配器是知道被適配者的詳細(xì)情況的(就是那個(gè)類(lèi)或那個(gè)接口)。裝飾者只知道其接口是什么,至于其具體類(lèi)型(是基類(lèi)還是其他派生類(lèi))只有在運(yùn)行期間才知道。

0x07.源碼中的裝飾者

BufferedReader

BufferInputStream/BufferOutputStream

Spring. TransactionAwareCacheDecorator

Mybatis. Cache

0x08.源碼

設(shè)計(jì)模式之裝飾著模式: https://github.com/sigmako/design-pattern/tree/master/decorator

0x09.參考

慕課網(wǎng)設(shè)計(jì)模式精講: https://coding.imooc.com/class/270.html

《JAVA與模式》之裝飾模式: https://www.cnblogs.com/java-my-life/archive/2012/04/20/2455726.html

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/75335.html

Failed to recv the data from server completely (SIZE:0/8, REASON:closed)