设计模式:装饰模式(Head First版)

装饰者模式:动态地将责任附加到对象上,若到扩展功能,装饰者提供了比继承更有弹性的替代方案。

UML图

有这样一个需求,咖啡店出售各式咖啡,如深焙、低卡、摩卡等,也有各种调料,如牛奶、奶泡等。

咖啡店需要根据咖啡中所放入的不同调料收取不同的费用。用装饰者模式来实现

定义一个抽象组件

package com.headfirst.chapter3;
/**
 * 定义了一个抽象类,用于表示组件,它定义了一个抽象方法cost
 */
public abstract class Beverage {
	String description; 

	public String getDescription() {
		return description;
	}

	public abstract double cost();//计费方法

}

下面两个是具体组件,也就是被装饰者

1,深焙咖啡

package com.headfirst.chapter3;

public class DarkRoast extends Beverage {//深焙咖啡

	public DarkRoast() {
		this.description = "DarkRoast";
	}
	
	public double cost() {
		return 0.89;
	}

}

2,混合咖啡

package com.headfirst.chapter3;

public class HouseBlend extends Beverage {

	public HouseBlend() {
		this.description = "HouseBlend";
	}
	public double cost() {
		return 1.89;
	}

}

装饰者

这里定义了一个抽象方法getDescription,那么子类必须它来增加描述

如Houseblend Milk

package com.headfirst.chapter3;

public abstract class CondimentDecorator extends Beverage {
	public abstract String getDescription();
}
 

 下面两个是装饰者

package com.headfirst.chapter3;

public class Milk extends CondimentDecorator {

	private Beverage beverage;//这个引用指向被装饰者

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

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

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

}
package com.headfirst.chapter3;

public class Mocha extends Beverage {

	Beverage beverage;

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

	public String getDescription() {
		return beverage.getDescription() + " Mocha";
	}
	
	public double cost() {
		return beverage.cost()+0.59;
	}

}
 

测试类:

package com.headfirst.chapter3;

public class Test {
	public static void main(String[] args) {
		Beverage darkRoast = new DarkRoast();
		darkRoast = new Mocha(darkRoast);
		darkRoast = new Milk(darkRoast);
		System.out.println(darkRoast.getDescription()+" $"+darkRoast.cost());
	}
}

 最后打印出:DarkRoast Mocha Milk $1.68


设计原则:类应该向修改关闭,向扩展开放
类的继承是扩展开幕式之一,但不见得是达到弹性设计的最佳方式。如果依赖继承,那么类的行为只能在编译时静态决定。
反之,利用组合,可以把装饰者混合着用,而且是在运行时。

猜你喜欢

转载自mynote.iteye.com/blog/1543296