最初接触装饰设计模式,一直搞不懂这么做的意义是什么,看了网上很多的资料,对于与继承的区别并没有很清楚的分析,直到看到这篇博客:http://www.cnblogs.com/rookieFly-tdiitd/p/4914593.html 这篇就很清楚的解释了装饰设计模式与继承之间的区别。下面是我自己的一些理解。
一、概念
装饰模式又称为包装模式,动态地给对象添加功能,是继承关系的一种替代方法。
二、选择
子类通过继承也能增加功能,但是关于装饰模式与继承之间如何选择,请看下面的例子。
假设:煎饼是父类,成员变量是money,也可以在煎饼上添加火腿、辣条、土豆丝、鸡蛋。如果使用子类继承父类的方式,那么要吃这么一个煎饼可能会出现多少种情况呢?
这里我们看到如果使用子类继承父类,那么我们要写很多子类,这么做无疑增加了程序的臃肿性,并不是很灵活。这时,装饰模式就诞生了。
三、格式
首先我们要有一个真实的对象和装饰对象,它们两个要实现同一个接口,还有有具体的装饰对象,简易的说就是将真实对象作为具体装饰对象的构造方法的参数,给装饰对象添加功能。
四、代码
接口类:
1 package Decorate; 2 3 public interface Jianbing { 4 //获取价格 5 public float getMoney(); 6 //返回煎饼的信息 7 public String description(); 8 }
抽象装饰类:
1 package Decorate; 2 //装饰的对象 3 public abstract class DecorateJianbing implements Jianbing { 4 private Jianbing jianbing; 5 6 public DecorateJianbing(Jianbing jianbing) { 7 super(); 8 this.jianbing = jianbing; 9 } 10 11 @Override 12 public float getMoney() { 13 14 return jianbing.getMoney(); 15 } 16 17 @Override 18 public String description() { 19 20 return jianbing.description(); 21 } 22 23 }
真实对象
1 package Decorate; 2 //真实的对象 3 public class TrueJianbing implements Jianbing { 4 5 @Override 6 public float getMoney() { 7 8 return 3f; 9 } 10 11 @Override 12 public String description() { 13 14 return "煎饼"; 15 } 16 17 }
抽象装饰类的具体类:
1 package Decorate; 2 3 public class Egg extends DecorateJianbing { 4 5 public Egg(Jianbing jianbing) { 6 super(jianbing); 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public float getMoney() { 12 13 return super.getMoney()+ 1f; 14 } 15 16 @Override 17 public String description() { 18 19 return super.description() + "+鸡蛋"; 20 } 21 22 }
1 package Decorate; 2 3 public class Huotui extends DecorateJianbing { 4 5 public Huotui(Jianbing jianbing) { 6 super(jianbing); 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public float getMoney() { 12 13 return super.getMoney()+1f; 14 } 15 16 @Override 17 public String description() { 18 19 return super.description()+"+火腿肠"; 20 } 21 22 }
1 package Decorate; 2 3 public class Latiao extends DecorateJianbing { 4 5 public Latiao(Jianbing jianbing) { 6 super(jianbing); 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public float getMoney() { 12 13 return super.getMoney()+0.5f; 14 } 15 16 @Override 17 public String description() { 18 19 return super.description()+"+辣条"; 20 } 21 22 }
1 package Decorate; 2 3 public class Tudousi extends DecorateJianbing { 4 5 public Tudousi(Jianbing jianbing) { 6 super(jianbing); 7 // TODO Auto-generated constructor stub 8 } 9 10 @Override 11 public float getMoney() { 12 13 return super.getMoney()+0.5f; 14 } 15 16 @Override 17 public String description() { 18 19 return super.description()+"+土豆丝"; 20 } 21 22 }
测试类:
1 public class DemoTest { 2 //这里可以任意组合,当然要把所有的组合,就要把这些一个个叠加上,就像最后一个例子 3 public static void main(String[] args) { 4 //无任何添加的煎饼 5 TrueJianbing tjb = new TrueJianbing(); 6 7 //加鸡蛋的煎饼 8 Egg egg = new Egg(tjb); 9 System.out.println(egg.description()+" 价格:"+egg.getMoney()); 10 11 //加辣条的煎饼 12 Latiao lt = new Latiao(tjb); 13 System.out.println(lt.description()+" 价格:"+lt.getMoney()); 14 15 //加鸡蛋 辣条 土豆丝 火腿肠 16 Tudousi tudousi = new Tudousi(lt); 17 Huotui huotui = new Huotui(tudousi); 18 egg = new Egg(huotui); 19 System.out.println(egg.description()+" 价格:"+egg.getMoney()); 20 21 } 22 23 }
打印:
煎饼+鸡蛋 价格:4.0 煎饼+辣条 价格:3.5 煎饼+辣条+土豆丝+火腿肠+鸡蛋 价格:6.0
我们可以将装饰的具体类任意组合,这样是不是比刚开始介绍的继承方法好多了呢?
那么我们就总结一下装饰模式有什么特点。
优点:
--装饰模式降低了类与类之间的耦合度,可以动态地增加或删除功能,装饰类及具体装饰类可以独立地进行变化,以便后期增加或者删除类。
--扩展对象功能,比继承要灵活,不会导致类的个数急剧地增加。
缺点:
--产生很多的小对象,大量的小对象会占用内存。
--组合方式很多,很容易出错。