设计模式之装饰者模式

设计模式之装饰者模式

简介

​ 装饰模式是在不使用继承和不改变原类文件的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

注意其中三点:

1,不改变原类文件。

2,不使用继承。

3,动态扩展。

优点:

  1. 装饰者模式与继承关系的目的都是要扩展对象的功能,但是装饰者可以提供比继承更多的灵活性。

  2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

组成角色:

  1. Component(抽象组件又叫被装饰对象的基类)

​ 定义一个对象接口,可以给这些对象动态地添加职责。

  1. ConcreteComponent(具体组件又叫具体被装饰对象)

​ 定义一个对象,可以给这个对象添加一些职责。

  1. Decorator(装饰者抽象类)

​ 维持一个指向Component实例的引用,并定义一个与Component接口一致的接口。

  1. ConcreteDecorator(具体装饰者)

​ 具体的装饰对象,给内部持有的具体被装饰对象,增加具体的职责。

具体例子:

如对一杯咖啡进行加料,有奶、糖、巧克力等,咖啡也分不同品种卡布奇诺、摩卡等

结构就看类图
在这里插入图片描述
Drink是最终成品,包含了装饰的类和被装饰类,再往下细分不同被装饰的类和细节装饰的类。

我们先分析出最终产品是顾客拿到的成品,成品类要有价格属性和描述加料的方法。

再往下分装饰类和被被装饰类,关键就是如何保证成品类的原有属性加上装饰类装饰。

装饰过程就是类似一个递归的过程。

在最开始的时候,对象是Drink子类Coffee的子类

Drink bm = new Mocha();

接着开始装饰后变为Drink子类Decoratord的子类

bm = new Milk(bm);

在milk类中可以用构造方法默认修饰,也可以调用其方法修饰。参数bm已经存于Decorator类的Drink属性中了,再次调用时

bm = new Milk(bm);

这个bm就不是最开始的Blue_Mountain类对象了,而是Decorator子类Milk类的对象了,由于装饰类Coffee和被装饰类Decorator都是Drink子类,所以参数没有问题。

在展示时

System.out.println(bm.getDes()+" "+bm.cost());

这个bm第一次调用getDes()方法是将本次装饰元素“牛奶”输出,并调用父类的Drink属性对象的getDes()方法,由于这个属性也是Milk类的对象所以就产生了类似递归的情况,由上文可知第二getDes()方法内的Drink属性不再是Milk对象了,而是最开始的Blue_Mountain类对象,在这个getDes()中不再调用getDes()方法于是就结束了递归。

getDes()方法

public String getDes(){    return super.getDes()+" "+super.getPrice()+"&&"+this.drink.getDes();}

结果

牛奶 4.0&&牛奶 4.0&&摩卡咖啡 15.0

牛奶 4.0(第一次getDes(),此时的this.drink对象是Milk类的)&&牛奶 4.0(第二次getDes(),此时的this.drink对象是Mocha类的)&&摩卡咖啡 15.0

下面附上完整代码:

public abstract class Drink {    
    
    public String des;    
    private double price = 0;   
    
    public Drink() {}    
    public String getDes() { return des;}    
    public void setDes(String des) {this.des = des;}    
    public double getPrice() {return price;}    
    public void setPrice(double price) { this.price = price;}    
    public double cost(){return price;}
}
public class Coffee extends Drink{    
    public double cost(){return super.getPrice();}
}
public class Decorator extends Drink {    
    private Drink drink;    
    public Decorator(Drink drink) {this.drink = drink;}    
    public double cost(){return super.getPrice()+this.drink.cost();}    
    public String getDes({
        returnsuper.getDes()+""+super.getPrice()+"&&"+this.drink.getDes();    
    }
}
public class Milk extends Decorator {    
    public Milk(Drink drink) {        
        super(drink);        
        this.setDes("牛奶");        
        this.setPrice(4.0);    
    }
}
public class Mocha extends Coffee{    
    public Mocha() {        
        super.setDes("摩卡咖啡");        
        super.setPrice(7.0);    
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值