设计模式之-装饰器模式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Smy_0114/article/details/80653127

参考https://blog.csdn.net/wwh578867817/article/details/51480441

下面有一般模式和装饰器模式对比。

一:先一般模式需要什么对象直接新建一个类,比如:咖啡,牛奶咖啡,加糖咖啡,糖牛奶咖啡等等越多越复杂。


1.饮料接口

package 一般模式;
/**
 * 饮料接口:可以是任何饮料,比如咖啡,茶,红牛······
 * 
 * @author smy
 *
 */
public interface Drink {
	/**
	 * 饮料的价格。
	 * @return
	 */
	public float cost();
	
	/**
	 * 饮料的描述,也就是饮料的名称,比如红牛,咖啡,茶······
	 * @return
	 */
	public String getDescription();
}

2.咖啡

package 一般模式;
/**
 * 咖啡饮料,实现了饮料接口。
 * @author smy
 *
 */
public class Coffee implements Drink {

	@Override
	public float cost() {
		// TODO 每杯售价10元人民币。
		return 10;
	}

	@Override
	public String getDescription() {
		// TODO 原味咖啡。
		return "咖啡";
	}

}

3.牛奶咖啡

package 一般模式;

public class MilkCoffee implements Drink{

	@Override
	public float cost() {
		// TODO Auto-generated method stub
		return 12;
	}

	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return "牛奶咖啡";
	}
	
}

4.糖咖啡

package 一般模式;

public class SugarCoffee implements Drink{

	@Override
	public float cost() {
		// TODO Auto-generated method stub
		return 11;
	}

	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return "加糖咖啡";
	}

}

5.牛奶糖咖啡

package 一般模式;

public class MilkSugarCoffee implements Drink{

	@Override
	public float cost() {
		// TODO Auto-generated method stub
		return 14;
	}

	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return "牛奶加糖咖啡";
	}

}

6.测试

package 一般模式;

public class App {
	public static void main(String[] args) {
		Drink drink = new MilkSugarCoffee();
		System.out.print(drink.cost());
		System.out.println(drink.getDescription());
		
		drink = new SugarCoffee();
		System.out.print(drink.cost());
		System.out.println(drink.getDescription());
		
		
		
		
	}
}

7.总结:一般模式这种实现也可以用,简单的业务可以,但涉及到复杂的就显得有点力不从心了。


二:装饰器模式,其实就是比一般模式多了个装饰类,具体的实现类需要继承此装饰类而已。


先来一张结构图


1.饮料接口不变

package 装饰器模式;
/**
 * 饮料接口:可以是任何饮料,比如咖啡,茶,红牛······
 * 
 * @author smy
 *
 */
public interface Drink {
	/**
	 * 饮料的价格。
	 * @return
	 */
	public float cost();
	
	/**
	 * 饮料的描述,也就是饮料的名称,比如红牛,咖啡,茶······
	 * @return
	 */
	public String getDescription();
}

2.咖啡不变

package 装饰器模式;
/**
 * 咖啡饮料,实现了饮料接口。
 * @author smy
 *
 */
public class Coffee implements Drink {

	@Override
	public float cost() {
		// TODO 每杯售价10元人民币。
		return 10;
	}

	@Override
	public String getDescription() {
		// TODO 原味咖啡。
		return "咖啡";
	}

}

3.装饰器

package 装饰器模式;
/**
 * 条件装饰器饮料,也是饮料当作是超级饮料,用来继承的。
 * @author smy
 *
 */
public abstract class CondimentDecorator implements Drink{
	protected Drink decoratorDrink;
	public CondimentDecorator (Drink decoratorDrink){
		this.decoratorDrink=decoratorDrink;
	}
	public CondimentDecorator ( ){
	}
	@Override
	public float cost() {
		// TODO Auto-generated method stub
		return decoratorDrink.cost();
	}
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return decoratorDrink.getDescription();
	}
	
	
	
}

4.牛奶

package 装饰器模式;

public class Milk extends CondimentDecorator{

	public Milk(Drink decoratorDrink) {
		super(decoratorDrink);
		// TODO Auto-generated constructor stub
	}
	
	
	

	@Override
	public float cost() {
		// TODO Auto-generated method stub
		return super.cost()+2;
	}
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return super.getDescription()+"牛奶味";
	}




	

}

5.糖

package 装饰器模式;

public class Sugar extends CondimentDecorator{

	public Sugar(Drink decoratorDrink) {
		super(decoratorDrink);
		// TODO Auto-generated constructor stub
	}
	
	@Override
	public float cost() {
		// TODO Auto-generated method stub
		return super.cost()+1;
	}
	
	
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return super.getDescription()+"加糖";
	}
	

}

6.冰块

package 装饰器模式;

public class Ice extends CondimentDecorator{

	public Ice(Drink decoratorDrink) {
		super(decoratorDrink);
		// TODO Auto-generated constructor stub
	}
	@Override
	public float cost() {
		// TODO Auto-generated method stub
		return super.cost()+5;
	}
	@Override
	public String getDescription() {
		// TODO Auto-generated method stub
		return super.getDescription()+"冰块";
	}

}

8.测试

package 装饰器模式;
/**
 * 假设我们现在去咖啡店要了一杯咖啡,可以加奶、加糖等等。咖啡和奶、糖分别有不同的价格。
 * 咖啡就是我们的组件,奶和糖是我们的装饰者,现在我们要计算调制这样一杯咖啡花费多少。
 * -----------------------------------------------------------------------------
 * @author smy
 *
 */
public class App {
	public static void main(String[] args) {
		
		Drink drink = new Coffee();
		System.out.print(drink.cost());
		System.out.println(drink.getDescription());
		
		drink=new Milk(drink);
		System.out.print(drink.cost());
		System.out.println(drink.getDescription());
		
		
		drink =new Sugar(drink);
		System.out.print(drink.cost());
		System.out.println(drink.getDescription());
		
		
		drink =new Ice(drink);
		System.out.print(drink.cost());
		System.out.println(drink.getDescription());
		
		
		
	}
}

9.总结:刚开始接触感觉装饰器模式更复杂,但是在熟悉之后装饰器模式是很不错的选择。


10.为什么要用装饰器模式:

装饰者模式(Decorator Pattern),是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。(包裹真是的对象,也就是装饰器类里面有原始对象
使用装饰者模式的时候需要注意一下几点内容:
(1)装饰对象和真实对象有相同的接口。这样客户端对象就可以以和真实对象相同的方式和装饰对象交互。(什么意思呢,就是说new一个装饰器对象可以指向公共的接口
(2)装饰对象包含一个真实对象的引用。
(3)装饰对象接受所有的来自客户端的请求,它把这些请求转发给真实的对象。
(4)装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。然而,装饰者模式,不需要子类可以在应用程序运行时,动态扩展功能,更加方便、灵活(意思就是不用改变coffee对象,只增加装饰的条件即可也就是糖,牛奶之类的对象,这跟普通模式增加子对象不同,此处增加的装饰条件可复用。)。

适用装饰者模式场合:
1.当我们需要为某个现有的对象,动态的增加一个新的功能或职责时,可以考虑使用装饰模式。
2.当某个对象的职责经常发生变化或者经常需要动态的增加职责,避免为了适应这样的变化,而增加继承子类扩展的方式,因为这种方式会造成子类膨胀的速度过快,难以控制。




猜你喜欢

转载自blog.csdn.net/Smy_0114/article/details/80653127