23种设计模式之装饰模式

23种设计模式之装饰模式

参考资料

下文如有错漏之处,敬请指正

一、简介

定义

动态的给一个对象增加额外的功能。

特点

  • 装饰者模式是一种结构型模式
  • 在对象扩展方面比继承更有弹性
  • 装饰者模式是从最里层(被装饰者)开始向外(装饰者)一一执行

通用类图

在这里插入图片描述
主要角色:

  • Component

    抽象主体角色(如咖啡)

  • ConcreteComponent

    具体主体角,被装饰者(如美式、摩卡、卡布奇诺)

    继承主体

  • Decorator

    抽象装饰者角色

    继承抽象主体并聚合抽象主体

  • ConcreteDecorator

    具体装饰者角色(巧克力、牛奶、芝士)

    继承抽象装饰者

优点

  • 装饰类和被装饰类都可以独立发展,不会相互耦合。

  • 装饰模式是继承关系的一个替代方案。装饰类Decorator,不管装饰多少层,返回的对象还是Component,实现的还是is-a的关系。

缺点

  • 多层装饰比较复杂。

应用场景

  • JDK中的 IO
  • 对象与对象之间发生逻辑上的组合关系(给不同权限用户分配不同功能,用户是被装饰者,功能是装饰者)
  • 动态增加功能,动态撤销。

二、装饰者模式

需求:

现在有一个咖啡馆要做一个订单系统,计算顾客所点的咖啡和调料的价格。咖啡有:摩卡、卡布奇诺、拿铁。调味品有:巧克力、牛奶、芝士。

抽象主体:

package decorator;

public abstract class Coffee {

	//  定义咖啡的描述信息
	private String desc;

	//  定义咖啡的价格
	private float cost;

	public String getDesc() {
		return this.desc + " " + this.cost;
	}

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

	public void setCost(float cost) {
		this.cost = cost;
	}

	//计算费用的抽象方法
	public float cost() {
		return this.cost;
	}

}

具体主体:

package decorator;

public class Cappuccino extends Coffee {
    public Cappuccino() {
        this.setDesc("卡布奇诺");
        this.setCost(21.00f);
    }

}
package decorator;

public class Latte extends Coffee {
    public Latte() {
        this.setDesc("拿铁");
        this.setCost(23.00f);
    }

}
package decorator;

public class Mocha extends Coffee {
    public Mocha() {
        this.setDesc("摩卡");
        this.setCost(22.00f);
    }


}

抽象装饰者

package decorator;

public abstract class Decorator extends Coffee {

	private Coffee coffee;

	public Decorator(Coffee coffee) {
		this.coffee = coffee;
	}

	@Override
	public String getDesc() {
		return coffee.getDesc() + " + " + super.getDesc();
	}

	@Override
	public float cost() {
		return coffee.cost() + super.cost();
	}
}

具体装饰者:

package decorator;

public class Chess extends Decorator {
    public Chess(Coffee coffee) {
        super(coffee);
        this.setDesc("芝士");
        this.setCost(10.00f);
    }


}
package decorator;

public class Chocolate extends Decorator {
    public Chocolate(Coffee coffee) {
        super(coffee);
        this.setDesc("巧克力");
        this.setCost(8.00f);
    }


}
package decorator;

public class Milk extends Decorator {

    public Milk(Coffee coffee) {
        super(coffee);
        this.setDesc("牛奶");
        this.setCost(6.00f);
    }


}

Client:

package decorator;

public class Client {
	public static void main(String[] args) {
		Coffee coffee = new Cappuccino();
		System.out.println("Desc: " + coffee.getDesc());
		System.out.println("Cost: " + coffee.cost() + "¥");

		coffee = new Milk(coffee);
		System.out.println("Desc: " + coffee.getDesc());
		System.out.println("Cost: " + coffee.cost() + "¥");

		coffee = new Chocolate(coffee);
		System.out.println("Desc: " + coffee.getDesc());
		System.out.println("Cost: " + coffee.cost() + "¥");

		coffee = new Chess(coffee);
		System.out.println("Desc: " + coffee.getDesc());
		System.out.println("Cost: " + coffee.cost() + "¥");

		/**
		 * 输出结果:
		 * Desc: 卡布奇诺 21.0
		 * Cost: 21.0¥
		 * Desc: 卡布奇诺 21.0 + 牛奶 6.0
		 * Cost: 27.0¥
		 * Desc: 卡布奇诺 21.0 + 牛奶 6.0 + 巧克力 8.0
		 * Cost: 35.0¥
		 * Desc: 卡布奇诺 21.0 + 牛奶 6.0 + 巧克力 8.0 + 芝士 10.0
		 * Cost: 45.0¥
		 */
	}
}

当要增加一种新咖啡品种时,只需要继承抽象主体,当增加一种调味品时,只需要继承抽象装饰者,不改变原有结构。

三、总结

  1. 装饰模式是对继承的有力补充。继承是静态地给类增加功能,而装饰模式则是动态地增加功能。
  2. 装饰模式还有一个非常好的优点——扩展性非常好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值