面向对象设计模式:结构型模式之装饰器模式

一、引入

  • 咖啡馆订购系统

  • Initial 初始

    • 4 种咖啡
      • House blend (混合咖啡)
      • Dark Roast (深度烘培)
      • Decaf (低咖啡因咖啡)
      • Espresso (意式浓缩咖啡)
        在这里插入图片描述
        在这里插入图片描述
  • 需求变更:客户可以加料(咖啡、牛奶、糖等)

    • steamed milk
    • soy
    • mocha
    • Whip

使用继承:类爆炸 NO
在这里插入图片描述
修改父类:Beverage
在这里插入图片描述
需求倘若变更:料种类增加、料价格变化,需要修改 Beverage 类

Classes should be open for extension, but closed for modification:开放封闭原则,对修改封闭

No

在这里插入图片描述

Decorator…

二、装饰器模式

aka:Wrapper (包装器)

2.1 Intent 意图
  • Attach additional responsibilities to an object dynamically. 可动态地将其他职责附加到对象上.
  • Decorators provide a flexible alternative to subclassing for extending functionality. 装饰器为扩展功能提供了一种替代子类化的灵活替代方案.
    • Dynamically extension
    • Better than inheritance
2.2 Applicability 适用性
  • To add responsibilities to individual objects dynamically without affecting other object.
  • When extension by subclassing is impractical. 当子类化扩展是不切实际的.
    • 如,子类数量爆炸
2.3 类图

在这里插入图片描述

  • Component: defines the interface for objects that can have responsibilities added to them dynamically. 为可以动态地添加职责的对象定义接口
  • ConcreteComponent: defines an object to which additional responsibilities can be attached. 定义一个可以附加其他责任的对象.
  • Decorator: maintains a reference to a Component object and defines an interface that conforms to Component’s interface. 维护对 Component 对象的引用,并定义一个符合 Component 接口的接口
  • ConcreteDecorator: adds responsibilities to the component. 向组件添加职责
2.4 优缺点
  • 优点
    • More flexibility than static inheritance. 比静态继承更灵活
      • With Decorators, responsibilities can be added and removed at runtime simply by attaching and detaching them.
    • 避免"类爆炸"
    • 通过排列和组合,可以创建许多行为组合
    • 装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能
  • 缺点
    • Lots of little objects
    • A decorator and its component are not same
    • 多层装饰比较复杂
2.5 应用实例:Java IO 类

InputStream and OutputStream 字节流
Reader and Writer 字符流
在这里插入图片描述
FilterInputStream:protected volatile InputStream in;
在这里插入图片描述
FilterInputStream 与 InputStream 为组合和被组合关系

与装饰器设计模式类图相符!

在这里插入图片描述

public class JavaIO {
	public static void main(String[] args) throws FileNotFoundException {
		// Open an InputStream.
		FileInputStream in = new FileInputStream("test.dat");
		// Create a buffered InputStream.
		BufferedInputStream bin = new BufferedInputStream(in);
		// Create a buffered, data InputStream.
		DataInputStream dbin = new DataInputStream(bin);
		// Create an unbuffered, data InputStream.
		DataInputStream din = new DataInputStream(in);
		// Create a buffered, pushback, data InputStream.
		PushbackInputStream pbdbin = new PushbackInputStream(dbin);
	}
}
2.6 应用实例:咖啡馆订购系统
  • 饮品抽象类:Beverage
public abstract class Beverage {
	protected String description = "Unknown Beverage";

	public String getDescription() {
		return description;
	}

	public abstract double cost();
}
  • 咖啡类:继承 Beverage
public class DarkRoast extends Beverage {

	public DarkRoast() {
		description = "DarkRoast";
	}

	public double cost() {
		return .99;
	}
}

public class Espresso extends Beverage {

	public Espresso() {
		description = "Espresso";
	}

	public double cost() {
		return 1.99;
	}
}
public class HouseBlend extends Beverage {

	public HouseBlend() {
		description = "House Blend Coffee";
	}

	public double cost() {
		return .89;
	}
}
  • 装饰器:CondimentDecorator
public abstract class CondimentDecorator extends Beverage {
	public abstract String getDescription();
}
  • 装饰器子类:ConcreteDecorator
public class Mocha extends CondimentDecorator {
	Beverage beverage;

	public Mocha(Beverage beverage) {
		this.beverage = beverage;
	}

	public String getDescription() {
		return beverage.getDescription() + ", Mocha";
	}

	public double cost() {
		return .20 + beverage.cost();
	}
}
public class Soy extends CondimentDecorator {
	Beverage beverage;

	public Soy(Beverage beverage) {
		this.beverage = beverage;
	}

	public String getDescription() {
		return beverage.getDescription() + ", Soy";
	}

	public double cost() {
		return .15 + beverage.cost();
	}
}

public class Whip extends CondimentDecorator {
	Beverage beverage;

	public Whip(Beverage beverage) {
		this.beverage = beverage;
	}

	public String getDescription() {
		return beverage.getDescription() + ", Whip";
	}

	public double cost() {
		return .10 + beverage.cost();
	}
}
  • 使用与测试:
public class StarbuzzCoffee {

	public static void main(String[] args) {
		Beverage beverage = new Espresso();
		System.out.println(beverage.getDescription() + " $" + beverage.cost());

		Beverage beverage2 = new DarkRoast();
		beverage2 = new Mocha(beverage2);
		beverage2 = new Mocha(beverage2);
		beverage2 = new Whip(beverage2);
		System.out.println(beverage2.getDescription() + " $" + beverage2.cost());

		Beverage beverage3 = new HouseBlend();
		beverage3 = new Soy(beverage3);
		beverage3 = new Mocha(beverage3);
		beverage3 = new Whip(beverage3);
		System.out.println(beverage3.getDescription() + " $" + beverage3.cost());
	}
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值