装饰者设计模式

装饰者设计模式

此设计模式遵循的设计原则之一:类应该支持扩展,而拒绝修改;

一、固定结构

已知接口A和其实现类C,需要装饰者创建代理类B,其中B为装饰者、C为被装饰者;
1.创建类B,并实现接口A;
2. 提供类B的构造方法,参数类型为A,用于接收A接口的其他实现类C;
3. 给类B添加类型为A成员变量,用于存放A接口的其他实现类;
4. 增强需要的方法;
5. 实现不需要增强的方法,方法体重调用成员变量存在的其他实现类对应的方法。

注:装饰者和被装饰者对象有相同的超类型,因为装饰者和被装饰者必须是一样的类型,这里利用继承是为了达到类型匹配,而不是利用继承获得行为

利用继承设计子类,只能在编译时静态决定,并且所有子类都会继承相同的行为;利用组合的做法扩展对象,就可以在运行时动态的进行扩展。装饰者模式遵循开放-关闭原则:类应该对扩展开放,对修改关闭。利用装饰者,我们可以实现新的装饰者增加新的行为而不用修改现有代码,而如果单纯依赖继承,每当需要新行为时,还得修改现有的代码。

A a = new C();
B b = new B(a);
class B implements A{
	private A a;
	public B(A a){
		this.a = a;
	}
	//增强方法
	public void close(){
		...	
	}
	//不需要增强的方法
	public void commit(){
		this.a.commit();
	}
}

二、装饰者模式特点

1. 装饰者和被装饰的对象有着相同的超类;
2. 装饰者类拥有被装饰者类的对象,一般是当构造参数传入;
3. 可以用多个装饰者去装饰一个对象;

三、案例

java实现-装饰者模式-星巴克[Head First 设计模式]

public abstract class Beverage {//装饰者与被装饰者共享的超类,这里是个抽象类
    protected String description="";
    public String getDescription(){
        return description;
    }
    public abstract double cost();
}

 public abstract class CondimentDecorator extends Beverage {//为装饰者的实现写的一个抽象类,所有装饰者继承该类
    public abstract String getDescription();//装饰者内部需要重写获取描述的方法,因为每装饰一次,就添加了新的配料
}

public class HouseBlend extends Beverage {//具体化了一个饮料类,混合咖啡
    public HouseBlend(){
        description="House Blend coffee";
    }
    @Override
    public double cost() {
        return 4.9;
    }
}
public class Milk extends CondimentDecorator {//具体化了一个配料类,牛奶
    protected Beverage beverage;
    public Milk(Beverage beverage){
        this.beverage=beverage;
    }
    @Override
    public String getDescription() {
        return beverage.getDescription()+",with milk";
    }
    @Override
    public double cost() {
        return 2.3+beverage.cost();
    }
}

public class Mocha extends CondimentDecorator {//具体化了一个配料类,抹茶
    protected Beverage beverage;
    public Mocha(Beverage beverage){
        this.beverage=beverage;
    }
    @Override
    public String getDescription() {
        return beverage.getDescription()+",with Mocha";
    }
    @Override
    public double cost() {
        return 3.1+beverage.cost();
    }
}

public class Starbuzz {
    public static void main(String[] args) {
        Beverage beverage=new Mocha(new Milk(new Mocha(new HouseBlend())));
        //如上就是一杯HouseBlend配上两份Mocha和一份Milk,博主没去星巴克喝过咖啡,这样配可以么= =
    	System.out.println(beverage.getDescription()+":"+beverage.cost());
    }

}

输出如下

House Blend coffee,with Mocha,with milk,with Mocha:13.4

继承与装饰者模式
装饰者模式中用到了继承,但是这里装饰者模式用继承是为了保证装饰者和被装饰者有共同的超类,而不是为了给被装饰的类扩展新的特性,而装饰者模式中新的特性是通过类与类的组合(has-a的关系)而得到的,所以把装饰者模式和继承看做同一类设计思想是不恰当的。

参考文章:
https://www.jianshu.com/p/c26b9b4a9d9e
设计模式 | 装饰者模式及典型应用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值