设计模式详解之————装饰者模式

定义

装饰者模式动态的将责任附加到对象上,若要拓展功能,装饰者提供了比继承更有弹性的替代方案。
换言之,装饰者模式动态地给一个对象添加一些额外的职责。就增加功能来说, Decorator模式相比生成子类更为灵活。该模式以对客 户端透明的方式扩展对象的功能。

适用情况

(1)在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
(2)处理那些可以撤消的职责。
(3)当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的 子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

成员

1.Component(被装饰对象的基类)
定义一个对象接口,可以给这些对象动态地添加职责。
2.ConcreteComponent(具体被装饰对象)
定义一个对象,可以给这个对象添加一些职责。
3.Decorator(装饰者抽象类)
维持一个指向Component实例的引用,并定义一个与Component接口一致的接口。
4.ConcreteDecorator(具体装饰者)
具体的装饰对象,给内部持有的具体被装饰对象,增加具体的职责。

类图

本来是很想把类图画出来的,奈何UML类图不会画,以后学了再补算了哈哈哈。

代码示例

以《深入浅出设计模式》中的星巴克案例来举例并实现:
话说星巴克卖饮料(Beverage),饮料分为很多种,比如浓缩咖啡(Espresso),或者豆浆(HouseBlend)等,有些顾客想要对饮料加糖(Sugar),有些想要加牛奶(Milk),有些加摩卡(Mocha),有些甚至要多份的牛奶,那么这个程序要怎么设计呢?
我们按照装饰者模式思考:
Component----->Beverage
ConcreteComponent----->Espresso,HouseBlend等
ConcreteDecorator---->Sugar,Milk,Mocha等
现在缺一个装饰者抽象类:
Decorator---->CondimentDecorator类

我们来建立代码逻辑:
Beverage 被装饰对象的基类

package JAVA装饰者模式;
/**
 * Author select you from me
 * func  被装饰对象的基类
 */
public abstract class Beverage {
	String description="Unknown Beverage";
	public String getDescription(){
		return description;
	}
	public abstract double cost();
}

Espresso 具体被装饰对象

package JAVA装饰者模式;
/**
 * Author select you from me
 * func  具体被装饰对象
 */
public class Espresso extends Beverage{
	public Espresso(){
		description="Espresso";
	}
	@Override
	public double cost() {
		return 1.99;
	}
}

HouseBlend 具体被装饰对象

package JAVA装饰者模式;
/**
 * Author select you from me
 * func  具体被装饰对象
 */
public class HouseBlend extends Beverage{
	public HouseBlend(){
		description="HouseBlend";
	}
	@Override
	public double cost() {
		return 0.89;
	}
}

CondimentDecorator 装饰者抽象类

package JAVA装饰者模式;
/**
 * Author select you from me
 * func   装饰者抽象类
 */
public abstract class CondimentDecorator extends Beverage{
	public abstract String getDescription();
}

Mocha 具体装饰者

package JAVA装饰者模式;
/**
 * Author select you from me
 * func  具体的装饰对象,给内部持有的具体被装饰对象,增加具体的职责。
 */
public class Mocha extends CondimentDecorator{
	Beverage beverage;
	public Mocha(Beverage beverage){
		this.beverage=beverage;
	}
	@Override
	public String getDescription(){
		return beverage.getDescription()+",Mocha";
	}
	@Override
	public double cost(){
		return 0.20+beverage.cost();
	}
}

Soy 具体装饰者

package JAVA装饰者模式;
/**
 * Author select you from me
 * func  具体的装饰对象
 */
public class Soy extends CondimentDecorator {
	Beverage beverage;
	public Soy(Beverage beverage){
		this.beverage = beverage;
	}
	@Override
	public String getDescription() {
		return beverage.getDescription()+",Soy";
	}
	@Override
	public double cost() {
		return 0.05+beverage.cost();
	}
}

Whip 具体装饰者

package JAVA装饰者模式;
/**
 * Author select you from me
 * func  具体的装饰对象,给内部持有的具体被装饰对象,增加具体的职责。
 */
public class Whip extends CondimentDecorator {
	Beverage beverage;
	public Whip(Beverage beverage){
		this.beverage = beverage;
	}

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

	@Override
	public double cost() {
		return 0.25+beverage.cost();
	}
}

主类:

package JAVA装饰者模式;

/**
 * Created by Administrator on 2019-7-22 0022.
 */
public class StarbuzzCoffe {
	public static void main(String[] args){
		Beverage beverage = new Espresso();
		System.out.println(beverage.description+"----"+beverage.cost());
		Beverage beverage1 = new HouseBlend();
		beverage1 = new Mocha(beverage1);
		beverage1 = new Mocha(beverage1);
		beverage1 = new Whip(beverage1);
		System.out.println(beverage1.getDescription()+"-----"+beverage1.cost());
		//这三段代码可能不好理解,如果理解不了,替换成下边的注释代码
		//Beverage beverage1 = new HouseBlend();
		//Beverage beverage2 = new Mocha(beverage1);
		//Beverage beverage3 = new Mocha(beverage2);
		//Beverage beverage4 = new Whip(beverage3);
		//System.out.println(beverage1.getDescription()+"-----"+beverage4.cost());
	}
}

小结

  • 继承属于扩展形式之一,但不见得是达到弹性设计的最佳方案。
  • 在我们的设计中,应该允许行为可以被扩展,而不须修改现有的代码。
  • 组合和委托可用于在运行时动态地加上新的行为。
  • 除了继承,装饰者模式也可以让我们扩展行为。
  • 装饰者模式意味着一群装饰者类, 这些类用来包装具体组件。
  • 装饰者类反映出被装饰的组件类型(实际上,他们具有相同的类型,都经过接口或继承实现)。
  • 装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
  • 你可以有无数个装饰者包装一个组件。
  • 装饰者一般对组建的客户是透明的,除非客户程序依赖于组件的具体类型。

作者:select you from me
链接:https://mp.csdn.net/mdeditor/95767335
来源:CSDN
转载请联系作者获得授权并注明出处。

你可能感兴趣的:(JAVA设计模式)