設計模式--第7篇(裝飾者模式)

一,裝飾者模式

裝飾者模式:
動態的將新功能附加到對象上,在功能擴展方面比繼承更具有彈性,體現了OCP原則;

二,原理類圖

在這裏插入圖片描述
意圖: 動態地給一個對象添加一些額外的職責。就增加功能來說,Decorator 模式相比生成子類更爲靈活。
適用性:

  1. 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。
  2. 處理那些可以撤消的職責。
  3. 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因爲類定義被隱藏,或類定義不能用於生成子類。

三,實例

抽象類

package com.neei.decorator;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/7  16:23
 * @Description: 遊學網
 * @throws:
 */
public abstract class Drink {

    private String desc;
    private double price = 0.0d;

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public abstract double cost();
}

緩存層

package com.neei.decorator.coffee;

import com.neei.decorator.Drink;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/7  16:25
 * @Description: 遊學網
 * @throws:
 */
public class Coffee extends Drink {

    @Override
    public double cost() {
        return super.getPrice();
    }
}

被裝飾物

package com.neei.decorator.coffee;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/7  16:29
 * @Description: 遊學網
 * @throws:
 */
public class Latte extends Coffee {
    public Latte() {
        setDesc("拿鐵咖啡");
        setPrice(8D);
    }
}

public class Civet extends Coffee {
    public Civet() {
        setDesc("貓屎咖啡");
        setPrice(88D);
    }
}

裝飾者

package com.neei.decorator;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/7  16:31
 * @Description: 遊學網
 * @throws:
 */
public class Decorator extends Drink {

    private Drink drink;

    public Decorator(Drink drink) {
        this.drink = drink;
    }

    @Override
    public double cost() {
        return super.getPrice() + drink.cost();
    }

    //輸出裝飾者信息
    @Override
    public String getDesc() {
        return super.getDesc() + ":" + super.getPrice() + "&&" + drink.getDesc() + ":" + drink.getPrice();
    }
}

裝飾物

package com.neei.decorator.season;

import com.neei.decorator.Decorator;
import com.neei.decorator.Drink;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/7  16:36
 * @Description: 遊學網
 * @throws:
 */
public class Chocolate extends Decorator {
    public Chocolate(Drink drink) {
        super(drink);
        setDesc("巧克力");
        setPrice(3D);
    }
}

public class Milk extends Decorator {

    public Milk(Drink drink) {
        super(drink);
        setDesc("牛奶");
        setPrice(2D);
    }
}

public class Sugar extends Decorator {

    public Sugar(Drink drink) {
        super(drink);
        setDesc("糖");
        setPrice(1D);
    }
}

調用

package com.neei.decorator;

import com.neei.decorator.coffee.Civet;
import com.neei.decorator.season.Chocolate;
import com.neei.decorator.season.Milk;
import com.neei.decorator.season.Sugar;

/**
 * @param
 * @Author: AaNeei
 * @Date: 2019/10/7  16:39
 * @Description: 遊學網
 * @throws:
 */
public class CoffeeBar {

    public static void main(String[] args) {

        //點一份貓屎,加糖,牛奶,巧克力各一份
        Drink drink = new Civet();
        System.out.println(drink.cost());
        System.out.println(drink.getDesc());
        //加糖
        drink = new Sugar(drink);
        System.out.println(drink.cost());
        System.out.println(drink.getDesc());
        //加牛奶
        drink=new Milk(drink);
        System.out.println(drink.cost());
        System.out.println(drink.getDesc());
        //加巧克力
        drink=new Chocolate(drink);
        System.out.println(drink.cost());
        System.out.println(drink.getDesc());

    }
}

四,源碼分析

JDK源碼中使用的裝飾者模式,如FilterInputStream

public class FilterInputStream extends InputStream {
    /**
     * The input stream to be filtered.
     */
    protected volatile InputStream in;
    ...
}

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