软件设计模式-装饰器模式-工厂模式

装饰器模式

之前我们说过软件设计模式的一个典型特征就是 使用面向接口而不是继承的编程 但是有种情况是特殊的 例如我们的装饰器模式 之所以需要装饰器模式 是因为需要运行时对某个类进行修饰 由于我们设计模式的准则是开放-关闭原则 即扩展性要较高 并且关闭修改 即我们肯定是不能够修改基类的 还要能增加新的特性 这就是为什么代码中不论是Beverage(饮料)还是Condiment(配料) 都需要一个共同的基类 因为要想不修改底层代码 还要增加新的特性 那么这不就是类继承的用法吗 虽然设计模式中我们不推荐使用继承 但要因事物而变 不能固定思维 通过使用继承我们可以将配料和饮料都定为同一类型 这样调用父类的方法就没有问题 最后通过类似于递归的方式 我们可以得到最终的结果 并且可以很好的保持运行时的扩展 可以可以看到我们的main方法中可以叠加不同种类的配料 这就达到了扩展 并且如果我们想增加一个配方 那么我们只需要再继承一个配料基类 或者 饮料基类 而不用改变基类的任何代码 然后最后在main方法中加以包装即可

/**  
* @Title: StarBuzzTest.java  
* @Package   
* @Description: TODO(用一句话描述该文件做什么)  
* @author Lustre  
* @date 2019年12月8日  
* @version V1.0  
*/
/**
* @author Nigel
* @version 创建文件时间:2019年12月8日 下午7:36:30
*/
/**  
* @ClassName: StarBuzzTest  
* @Description: TODO(这里用一句话描述这个类的作用)  
* @author Nigel  
* @date 2019年12月8日  
*    
*/

/**
 * 
* @ClassName: Beverage  
* @Description: 定义一个抽象基类 之所以这里用基类而不是接口 是因为调料必须和饮料是同一个基类! 不然装饰器模式就是空谈
* @author Nigel  
* @date 2019年12月8日  
*
 */
abstract class Beverage{
   
	protected String description;
	
	public String getDescription() {
   
		return description;
	}
	
	/**
	 * 
	* @Title: cost  
	* @Description: 这个cost方法是需要被所有继承的实体类所重写的 因为每个实体必定有一个价钱 并且价钱也是不一致的
	* @return    
	* @return Double    
	* @throws
	 */
	abstract Double cost();
}

/**
 * 
* @ClassName: CondimentDecorator  
* @Description: 调料必须继承饮料类 这样才能发挥装饰类的特点!
* @author Nigel  
* @date 2019年12月8日  
*
 */
abstract class CondimentDecorator extends Beverage{
   
	protected Beverage superClassBeverage;
	/**
	 * 
	* <p>Title: getDescription</p>  
	* <p>Description: 每个调料对应的修饰自然也是不一样的
	* @return  
	* @see Beverage#getDescription()
	 */
	public abstract String getDescription();
}

/**
 * 
* @ClassName: Espresso  
* @Description: 此时为实体类 即实体饮料
* @author Nigel  
* @date 2019年12月8日  
*
 */
class Espresso extends Beverage {
   
	
	public Espresso() {
   
		// TODO Auto-generated constructor stub
		description = "Espresso";
	}
	
	@Override
	Double cost() {
   
		// TODO Auto-generated method stub
		return 1.99;
	}
	
}

class HouseBlend extends Beverage {
   
	
	/**  
	* 创建一个新的实例 HouseBlend.  
	*    
	*/
	public HouseBlend() {
   
		// TODO Auto-generated constructor stub
		description = "HouseBlend";
	}
	
	@Override
	Double cost() {
   
		// TODO Auto-generated method stub
		return .89;
	}
	
}

class DarkRoast extends Beverage {
   
	
	/**  
	* 创建一个新的实例 DarkRoast.  
	*    
	*/
	public DarkRoast() {
   
		// TODO Auto-generated constructor stub
		description = "DarkRoast";
	}
	
	@Override
	Double cost() {
   
		// TODO Auto-generated method stub
		return .99;
	}
	
}

class Decaf extends Beverage {
   
	
	/**  
	* 创建一个新的实例 Decaf.  
	*    
	*/
	public Decaf() {
   
		// TODO Auto-generated constructor stub
		description = "Decaf";
	}
	
	@Override
	Double cost() {
   
		// TODO Auto-generated method stub
		return 1.05;
	}
	
}


//接下来让调料进行实例化 其基类也是Beverage
class Mocha extends CondimentDecorator {
   
	 
	
	/**  
	* 创建一个新的实例 Mocha.  需要提供一个参数来附加到对应的饮料实体上
	*    
	*/
	public Mocha(Beverage beverage) {
   
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	/**
	* <p>Title: getDescription</p>  
	* <p>Description:之所以要重写getDescription 是因为对于调料而言 我们是要叠加上去的 所以还需要返回上级的描述!
	* @return  
	* @see CondimentDecorator#getDescription()  
	*/  
	@Override
	public String getDescription() {
   
		// TODO Auto-generated method stub
		return superClassBeverage.getDescription() + "Mocha";
	}

	/**
	* <p>Title: cost</p>  
	* <p>Description: </p>  
	* @return  
	* @see Beverage#cost()  
	*/  
	@Override
	Double cost() {
   
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .20;
	}
	
}

class Milk extends CondimentDecorator {
   
	
	/**  
	* 创建一个新的实例 Milk.  
	*    
	*/
	public Milk(Beverage beverage) {
   
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	@Override
	public String getDescription() {
   
		// TODO Auto-generated method stub
		return superClassBeverage.description + "Milk";
	}

	@Override
	Double cost() {
   
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .10;
	}
	
}

class SoyaBean extends CondimentDecorator {
   
	/**  
	* 创建一个新的实例 SoyaBean.  
	*    
	*/
	public SoyaBean(Beverage beverage) {
   
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
				
	}

	@Override
	public String getDescription() {
   
		// TODO Auto-generated method stub
		return superClassBeverage + "SoyaBean";
	}

	@Override
	Double cost() {
   
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .15;
	}
	
}

class Whip extends CondimentDecorator {
   
	
	/**  
	* 创建一个新的实例 Whip.  
	*    
	*/
	public Whip(Beverage beverage) {
   
		// TODO Auto-generated constructor stub
		superClassBeverage = beverage;
	}
	
	@Override
	public String getDescription() {
   
		// TODO Auto-generated method stub
		return superClassBeverage.getDescription() + "Whip";
	}
	
	/**
	 * 
	* <p>Title: cost</p>  
	* <p>Description: 以一种递归的方式来计算cost价格
	* @return  
	* @see Beverage#cost()
	 */
	@Override
	Double cost() {
   
		// TODO Auto-generated method stub
		return superClassBeverage.cost() + .10;
	}
	
}

public class StarBuzzTest {
   

	/**  
	* @Title: main  
	* @Description: TODO  
	* @param args    
	* @return void    
	* @throws
	*/
	public static void main(String[] args) {
   
		//进行测试
		System.out.print("不加配料的情况下:");
		Beverage decafBeverage = new Decaf();//实例化一个decaf低咖啡因
		System.out.println(decafBeverage.getDescription());//打印一下description
		System.out.print("价钱:");
		System.out.println(decafBeverage.cost());
		//加上Milk后的描述和价钱
		System.out.print("加Milk后的情况:");
		CondimentDecorator decafWithMilk = new Milk(decafBeverage);
		System.out.println( decafWithMilk.getDescription() );
		System.out.print("价钱:");
		System.out.printf("%.2f\n", decafWithMilk.cost());
		//加Mocha后的情况
		CondimentDecorator decafWithMilkAndMocha = new Mocha(decafWithMilk);
		System.out.printf("再加上Mocha后的情形:");
		System.out.println(decafWithMilkAndMocha.
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值