装饰者模式

mac2022-06-30  77

转自  http://blog.csdn.net/droyon/article/details/8630106

 

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

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

案例情景:

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

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

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

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

源代码下载

Pancake.java//煎饼果子

 

[java] view plain copy print ? publicclass Pancake {      public Pancake() {      };      public String toString(){          return"[煎饼:一个鸡蛋,一个脆饼--4元一个]";      }      publicint cost(){          return4;      }  }  public class Pancake { public Pancake() { }; public String toString(){ return "[煎饼:一个鸡蛋,一个脆饼--4元一个]"; } public int cost(){ return 4; } }

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

 

 

[java] view plain copy print ? publicclass DecoratorEggs extends Pancake{      Pancake mPancake;      privateint mEggsCount;      public DecoratorEggs(Pancake p,int count){          mPancake = p;          mEggsCount = count;      }      @Override      public String toString() {          return mPancake.toString() + "[+"+mEggsCount+"个鸡蛋--1元1个]";      }      @Override      publicint cost() {          return mPancake.cost()+1*mEggsCount;      }        }  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//装饰者,加辣椒

 

 

[java] view plain copy print ? publicclass DecoratorPepper extends Pancake{      Pancake mPancake;      public DecoratorPepper(Pancake p){          mPancake = p;      }      @Override      public String toString() {          return mPancake.toString()+"[放辣椒]";      }      @Override      publicint cost() {          return mPancake.cost();      }        }  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//装饰者,香肠装饰煎饼果子

 

 

[java] view plain copy print ? publicclass DecoratorPepper extends Pancake{      Pancake mPancake;      public DecoratorPepper(Pancake p){          mPancake = p;      }      @Override      public String toString() {          return mPancake.toString()+"[放辣椒]";      }      @Override      publicint cost() {          return mPancake.cost();      }        }  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//测试类

 

 

[java] view plain copy print ? publicclass DecoratorTest {      publicstaticvoid 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());                }  }  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

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)