Java设计模式之装饰者模式

装饰者模式

写在前面:

1.不要可以去使用设计模式,适合的才是最好的。

2.设计模式是一种思想,而不是一种规范,你可以让他变得更适合你。

1.基本概念

装饰者模式的核心是运行时扩展,类使用相同的接口相同的接口,但是增加了不同的责任。

动态的将责任附加到对象上,若要扩展功能,装饰者模式提供了比继承更有弹性的替代方案。

2.主要设计

装饰者模式 将类分为 基本组件 和 装饰组件,关系是这样的 :

  1. 基本组件 和 装饰组件 必须继承自同一个抽象类,也就是有相同的父类,也就是从根本上装饰组件和基本组件是相同的
  2. 装饰组件中持有装饰组件或基本组件的引用,然后利用装饰组件和基本组件实现自己想特定实现的方法,也就是装饰原先组件的功能
  3. 但是从外部看起来他仍旧是跟原来组件继承自相同父类

3.一个使用装饰者实现的例子

3.1问题描述:

  • @有一间咖啡店
  • @有多种咖啡: 摩卡(mokaCoffee 价格10)黑咖啡(blackCoffee价格20)。。。
  • @使用多种调料:牛奶(Milk 价格2.2)泡沫(Bubble 价格1.4)糖(Sugar 价格0.9)
  • @要求:根据使用咖啡种类不同,加的调料不同,收费也不同
  • @后期需求扩展:添加咖啡种类(ChinaCoffee),添加调料种类(Ice),使用双倍牛奶

3.2设计分析:

可以看得出来,咖啡是作为基本组件,也就是被装饰者,调料作为装饰组件,也就是装饰组件。使用一个饮料(Drink)抽象类作为父类,咖啡(coffee)继承自这个抽象类,调料也继承自这个抽象类,用调料装饰咖啡,返回的仍旧是一个饮料对象,可以继续被装饰.

Java设计模式之装饰者模式_第1张图片

3.3代码

饮料接口

interface Drink {   
    String decribe();
    double Cost();
}

两种咖啡

public class BlackCoffee implements Drink{

    private double cost;

    public BlackCoffee() {
        this.cost = CostList.blackCoffee;
    }

    @Override
    public double Cost() {
        // TODO Auto-generated method stub
        return this.cost;
    }

    @Override
    public String decribe() {
        // TODO Auto-generated method stub
        return "纯正的黑咖啡~\n";
    }
}
public class mokaCoffee implements Drink{

    private double cost;
    public mokaCoffee() {
        this.cost = CostList.mokaCoffee;
    }

    @Override
    public String decribe() {
        // TODO Auto-generated method stub
        return "最新配摩卡咖啡~\n";
    }

    @Override
    public double Cost() {
        // TODO Auto-generated method stub
        return this.cost;
    }

}

n种调料

//气泡
public class Bubble implements Drink{
    private Drink drinkInside;
    private double cost;

    public Bubble(Drink drinkInside) {
        super();
        this.drinkInside = drinkInside;
        this.cost = CostList.Milk;
    }

    @Override
    public double Cost() {
        // TODO Auto-generated method stub
        return this.cost + drinkInside.Cost();
    }

    @Override
    public String decribe() {
        // TODO Auto-generated method stub
        return this.drinkInside.decribe()+"添加了软软的泡沫~\n";
    }

}

牛奶

public class Milk implements Drink{
    private Drink drinkInside;
    private double cost;


    public Milk(Drink drinkInside) {
        super();
        this.drinkInside = drinkInside;
        this.cost = CostList.Milk;
    }

    @Override
    public double Cost() {
        // TODO Auto-generated method stub
        return this.cost + drinkInside.Cost();
    }

    @Override
    public String decribe() {
        // TODO Auto-generated method stub
        return this.drinkInside.decribe() + "添加了香滑的牛奶~\n";
    }
}

糖果

public class Sugar implements Drink{
    private Drink drinkInside;
    private double cost;


    public Sugar(Drink drinkInside) {
        super();
        this.drinkInside = drinkInside;
        this.cost = CostList.Milk;
    }

    @Override
    public double Cost() {
        // TODO Auto-generated method stub
        return this.cost + drinkInside.Cost();
    }

    @Override
    public String decribe() {
        // TODO Auto-generated method stub
        return this.drinkInside.decribe() + "添加了甜甜的糖果~\n";
    }

}

测试一下

public class DecratorModel {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Drink drink = null;
        System.out.println("选择您要的咖啡!---1.mokaCoffee 2.blackCoffee");
        int coffee = sc.nextInt();
        switch (coffee) {
        case 1:
            drink = new mokaCoffee();
            break;
        case 2:
            drink = new BlackCoffee();
            break;
        default:
            System.out.println("输入有误");
        }
        int other;
        while (true) {

            System.out.println("您要添加什么调料呢?---0.退出 1.牛奶 2.泡沫 3.糖");
            other = sc.nextInt();
            if(other == 0)break;
            switch (other) {
            case 1:
                drink = new Milk(drink);
                break;
            case 2:
                drink = new Bubble(drink);
                break;
            case 3:
                drink = new Sugar(drink);
                break;
            default:
                System.out.println("输入有误");
            }
        }
        System.out.println("您选择的是 :\n" + drink.decribe());
        System.out.println("价格是 :\n" + drink.Cost());
    }
}

输出的结果可以获得饮料的价格和相关配料的描述

功能扩展:

  1. 添加咖啡种类(ChinaCoffee),新建一个基本组件即可
  2. 添加调料种类冰(Ice),新建一个装饰组件即可
  3. 使用双倍牛奶,这个已经实现了,使用两次牛奶装饰

这样可以有效的使程序解耦,增加或减少功能时能尽量少的修改当前已经有的代码。

java中的IO流也同样使用了装饰者模式,InputStream和OutputStream作为被装饰者,缓存流作为装饰者,为原先的输入输出流增加了数据缓存的功能。转换流作为装饰者,增加了字节流向字符流装换的功能。。。。。

你可能感兴趣的:(java,java设计模式,装饰者模式)