装饰者模式

转自  http://blog.youkuaiyun.com/droyon/article/details/8630106

 

装饰者模式:顾名思义将对象装饰的更加漂亮,只是更漂亮,他还是他,没有改变类型。

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

案例情景:

煎饼果子(pancake),包含一个鸡蛋、一个脆饼。我们可以选择加辣椒(pepper),可以选择加香肠(Sausage),可以选择多加鸡蛋(Eggs)。(上地软件园路上的煎饼果子,你懂的!)

我们要实现对每一个煎饼果子进行描述。例如:”煎饼果子、不要辣椒“

我们如果为每一个煎饼果子都构建一个类,比如 PancakeWithPepper、PancakeWithSausage,那么我们就制造了一个维护的噩梦,比如如果多加一个蛋,可以写PancakeWithONeEggs、那么多加俩蛋那、仨蛋那?PancakeWithThreeEggs?

装饰着模式可以很好的解决这类问题。

源代码下载

Pancake.java//煎饼果子

 

  1. publicclass Pancake { 
  2.     public Pancake() { 
  3.     }; 
  4.     public String toString(){ 
  5.         return"[煎饼:一个鸡蛋,一个脆饼--4元一个]"
  6.     } 
  7.     publicint cost(){ 
  8.         return4
  9.     } 
public class Pancake {
	public Pancake() {
	};
	public String toString(){
		return "[煎饼:一个鸡蛋,一个脆饼--4元一个]";
	}
	public int cost(){
		return 4;
	}
}

DecoratorEggs.java//装饰者,用鸡蛋装饰煎饼果子

 

 

  1. publicclass DecoratorEggs extends Pancake{ 
  2.     Pancake mPancake; 
  3.     privateint mEggsCount; 
  4.     public DecoratorEggs(Pancake p,int count){ 
  5.         mPancake = p; 
  6.         mEggsCount = count; 
  7.     } 
  8.     @Override 
  9.     public String toString() { 
  10.         return mPancake.toString() + "[+"+mEggsCount+"个鸡蛋--1元1个]"
  11.     } 
  12.     @Override 
  13.     publicint cost() { 
  14.         return mPancake.cost()+1*mEggsCount; 
  15.     } 
  16.      
public class DecoratorEggs extends Pancake{
	Pancake mPancake;
	private int mEggsCount;
	public DecoratorEggs(Pancake p,int count){
		mPancake = p;
		mEggsCount = count;
	}
	@Override
	public String toString() {
		return mPancake.toString() + "[+"+mEggsCount+"个鸡蛋--1元1个]";
	}
	@Override
	public int cost() {
		return mPancake.cost()+1*mEggsCount;
	}
	
}

DecoratorPepper.java//装饰者,加辣椒

 

 

  1. publicclass DecoratorPepper extends Pancake{ 
  2.     Pancake mPancake; 
  3.     public DecoratorPepper(Pancake p){ 
  4.         mPancake = p; 
  5.     } 
  6.     @Override 
  7.     public String toString() { 
  8.         return mPancake.toString()+"[放辣椒]"
  9.     } 
  10.     @Override 
  11.     publicint cost() { 
  12.         return mPancake.cost(); 
  13.     } 
  14.      
public class DecoratorPepper extends Pancake{
	Pancake mPancake;
	public DecoratorPepper(Pancake p){
		mPancake = p;
	}
	@Override
	public String toString() {
		return mPancake.toString()+"[放辣椒]";
	}
	@Override
	public int cost() {
		return mPancake.cost();
	}
	
}

DecoratorSausage.java//装饰者,香肠装饰煎饼果子

 

 

  1. publicclass DecoratorPepper extends Pancake{ 
  2.     Pancake mPancake; 
  3.     public DecoratorPepper(Pancake p){ 
  4.         mPancake = p; 
  5.     } 
  6.     @Override 
  7.     public String toString() { 
  8.         return mPancake.toString()+"[放辣椒]"
  9.     } 
  10.     @Override 
  11.     publicint cost() { 
  12.         return mPancake.cost(); 
  13.     } 
  14.      
public class DecoratorPepper extends Pancake{
	Pancake mPancake;
	public DecoratorPepper(Pancake p){
		mPancake = p;
	}
	@Override
	public String toString() {
		return mPancake.toString()+"[放辣椒]";
	}
	@Override
	public int cost() {
		return mPancake.cost();
	}
	
}

DecoratorTest.java//测试类

 

 

  1. publicclass DecoratorTest { 
  2.     publicstaticvoid main(String args[]){ 
  3.         Pancake pancake = new Pancake();//一个普通煎饼  
  4.         System.out.println(pancake+"价格:"+pancake.cost()); 
  5.          
  6.         Pancake decoratorEggs = new DecoratorEggs(pancake, 2);//多加两个鸡蛋,用鸡蛋装饰煎饼  
  7.         System.out.println(decoratorEggs+"价格:"+decoratorEggs.cost()); 
  8.          
  9.         DecoratorPepper decoratorEggsAndPepper = new DecoratorPepper(decoratorEggs);//用两个鸡蛋装饰之后哦再用辣椒装饰它  
  10.         System.out.println(decoratorEggsAndPepper+"价格:"+decoratorEggsAndPepper.cost()); 
  11.          
  12.         Pancake pancakeWithEggsWithPepperWithSausage = new DecoratorSausage(decoratorEggsAndPepper);//继续装饰,用香肠装饰  
  13.         System.out.println(pancakeWithEggsWithPepperWithSausage+"价格:"+pancakeWithEggsWithPepperWithSausage.cost()); 
  14.          
  15.         DecoratorSausage decoratorSausage = new DecoratorSausage(new DecoratorEggs(new DecoratorPepper(new Pancake()), 1));//另外一个煎饼  
  16.         decoratorSausage.setSausage(2); 
  17.         System.out.println(decoratorSausage+"价格:"+decoratorSausage.cost()); 
  18.          
  19.     } 
public class DecoratorTest {
	public static void main(String args[]){
		Pancake pancake = new Pancake();//一个普通煎饼
		System.out.println(pancake+"价格:"+pancake.cost());
		
		Pancake decoratorEggs = new DecoratorEggs(pancake, 2);//多加两个鸡蛋,用鸡蛋装饰煎饼
		System.out.println(decoratorEggs+"价格:"+decoratorEggs.cost());
		
		DecoratorPepper decoratorEggsAndPepper = new DecoratorPepper(decoratorEggs);//用两个鸡蛋装饰之后哦再用辣椒装饰它
		System.out.println(decoratorEggsAndPepper+"价格:"+decoratorEggsAndPepper.cost());
		
		Pancake pancakeWithEggsWithPepperWithSausage = new DecoratorSausage(decoratorEggsAndPepper);//继续装饰,用香肠装饰
		System.out.println(pancakeWithEggsWithPepperWithSausage+"价格:"+pancakeWithEggsWithPepperWithSausage.cost());
		
		DecoratorSausage decoratorSausage = new DecoratorSausage(new DecoratorEggs(new DecoratorPepper(new Pancake()), 1));//另外一个煎饼
		decoratorSausage.setSausage(2);
		System.out.println(decoratorSausage+"价格:"+decoratorSausage.cost());
		
	}
}

测试结果:

 

[煎饼:一个鸡蛋,一个脆饼--4元一个]价格:4 [煎饼:一个鸡蛋,一个脆饼--4元一个][+2个鸡蛋--1元1个]价格:6 [煎饼:一个鸡蛋,一个脆饼--4元一个][+2个鸡蛋--1元1个][放辣椒]价格:6 [煎饼:一个鸡蛋,一个脆饼--4元一个][+2个鸡蛋--1元1个][放辣椒][加0根香肠--2元一根]价格:6 [煎饼:一个鸡蛋,一个脆饼--4元一个][放辣椒][+1个鸡蛋--1元1个][加2根香肠--2元一根]价格:9

 

总结:

继承可以扩展类的功能,但不见得是最好的方案。继承可以从父类那里得到定义好的属性和方法,但继承在实现起来不具备弹性。继承的行为是在编译时就决定好的,而且所有的子类都继承得到相同的行为。组合可以扩展对象的行为,在运行时动态的进行扩展。利用组合维护代码,通过动态的改变组合对象,可以实现不需要改变代码添加新功能的行为。

开放关闭原则:类应该对扩展开放,对修改关闭。---设计原则

在不需要改变代码的情况下,扩展类的行为。比如观察者模式,通过加入新的观察者,不需要修改主题的代码,我们可以在任何时候扩展类的行为。 装饰者对象和被装饰的对象拥有相同的超类型,也就是说,装饰之后,被装饰对象的类型不能变。这样在任何时候就可以通过新的装饰者装饰它。

 

在java语言中,我们看到的io操作,也就是流,他们也是装饰者对象的例子。InputStream可以读取字节,然后显示,BufferedInputStream包装了InputStream,将InputStream读取的内容放在缓冲区中,在读取结束后,一起显示。

转载于:https://www.cnblogs.com/Dennis-mi/articles/3346727.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值