Java设计模式之装饰者模式

来源:互联网 发布:加密db数据库怎么打开 编辑:程序博客网 时间:2024/05/22 17:39

装饰者模式


写在前面:

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)继承自这个抽象类,调料也继承自这个抽象类,用调料装饰咖啡,返回的仍旧是一个饮料对象,可以继续被装饰.

这里写图片描述


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作为被装饰者,缓存流作为装饰者,为原先的输入输出流增加了数据缓存的功能。转换流作为装饰者,增加了字节流向字符流装换的功能。。。。。

0 0
原创粉丝点击