今天开始学历了JAVA设计模式中的装饰模式,照例还是写下自己理解的心得吧。
装饰器模式,啥是装饰器模式?带着这个问题,咱们好好的去火锅店吃个火锅。
“老板,来份全辣锅底,不要给我用装饰器模式来配料!”我特地狠狠的强调了最后一句话。
不到一会,老板给我端来了一个火锅和几个盘子,火锅里装了盐水,而盘子里放了辣椒,花椒,茴香,大蒜等佐料。。。。。。。。。。
这时候大家可能就需要问了,这咋吃啊。。。难道让我自己配料么?
这便是是我们的矛盾了!客户需要的一盘已经配好料的火锅汤底,但是我们初期给用户的锅里面或许只有盐水,我们不可能把原料给客户,让客户自己配料。
那么回到我们的装饰器模式上来,用咱们吃火锅的术语来解释下,把原先给客户的盐水锅底加上配料,使之成为客户需要的全辣火锅底料。
现在,我们就用代码来实现这个装饰的过程。
前序,我们先定义出一个抽象类,这个抽象类叫食料类,他里面有个方法叫入锅。
/** * 食料Food * @author * */ public abstract class Food { //食料有一个抽象方法,叫入锅,请原谅,我的英文就那么回事了,用拼音把。 abstract public void ruguo(); }
再来一口锅
public class Guo { Food food; //定义一个煮的方法,煮的对象是食物 public void zhu(Food food){ this.food = food; food.ruguo(); System.out.print("开锅开吃"); } }
第一步,我们线在火锅内加入盐水
为了区分,我们在命名后面加上一个代表是被装饰者
public class Shui extends Food { @Override public void ruguo() { System.out.println("在锅里加入2升盐水"); } }
先在盐水里加入辣椒呗,这里要注意,辣椒属于一个装饰对象,必须要需要一个相同类型的被装饰对象,如果没有被装饰的对象,辣椒的单独存在就没有任何意义。下同
public class Lajiao extends Food { Food food; Lajiao(Food food){ this.food=food; } @Override public void ruguo() { food.ruguo(); System.out.println("在锅里加入3个辣椒"); } }
public class Dasuan extends Food { Food food; Dasuan(Food food){ this.food=food; } @Override public void ruguo() { food.ruguo(); System.out.println("在锅里加入2片大蒜"); } }
public class Huixiang extends Food { Food food; Huixiang(Food food){ this.food=food; } @Override public void ruguo() { food.ruguo(); System.out.println("在锅里加入5片茴香"); } }
好,我们来测试下,开锅
public class Tset { public static void main(String[] args) { //先来一口锅 Guo guo = new Guo(); //先准备一锅盐水--------->被装饰的对象 Food shui = new Shui(); //将辣椒放入盐水中------------->装饰器 Food lajiao = new Lajiao(shui); //将大蒜加入辣椒盐水中---------->装饰器 Food dasuan = new Dasuan(lajiao); //将茴香加入大蒜辣椒盐水中------->装饰器 Food huixiang = new Huixiang(dasuan); //统一放入锅中,开煮 guo.zhu(huixiang); } }
好了,顺利开吃。。这样一锅火锅就煮好了。。。。
写好这样的代码之后,其实我们会发现,面向对象的思想会让我们代码如此的灵活。
假如我们不需要吃全辣火锅,只需要不加入辣椒即可。。。。
如果我们要吃干锅牛蛙,只需要再准备一个干锅牛蛙的适配器即可。。。
写到这,我突然发现,原来面向的思想在我们的生活如此的随处可见,一个厨师很简单的配菜过程就是一个装饰器的模式体现,是不是这或许也是JAVA那么受到欢迎的原因?
好了,又到了总结的时刻了。。。
适配器模式到底是什么?说白了就是一句话,给原有的对象随心所欲的添加你需要的功能。
但是适配器模式又需要满足几个原则。
1.身为装饰器必须要去装饰一个对象,就像我们上面提到的这些配料,离开了盐水其实一点意义都没有!
2.装饰器和被装饰的对象必须继承实现同一个接口或者继承于同一个抽象类。就如同我们的盐水,配料都需要实现放入火锅这个方法,当然啦,怎么样放入由他们自己去实现。就如同水要2升,大蒜只需要3片一样。
写到这,我突然感觉装饰器和适配器有些分不清。。。。。
适配器是一个单独的类,是一个中间件,兼容老的接口,实现新的接口。同时对两方面负责。适配器瞻前顾后。
适应的场景,如原有传一个参数可以获取数据,现在需要两个参数才能获取到数据了。
有些人可能会说,直接重载原有类的方法不就行了吗?
记住,我们在开发中可能是调用他人的包或者他人的方法,而开发时候的原则应该是不能随意的修改他人的类,这时候我们开发一个适配器的类是最为适合不过的了。
而装饰器,顾前不顾后。
丰富原有方法事原有的方法更加能符合客户的需要。但是要保证原有的方法也正常使用。
适应的场景,原有方法A打印出客户的姓名。新方法要打印客户的姓名和性别。这时候我们可以用新建一个装饰器,在打印完姓名之后再新增打印性别的代码。
但是不管是什么样的设计模式,总有一个原则。
对内修改关闭,对外扩展开发
本文原创哦,需要转载请注明出处,谢谢各位了。
原文地址:http://blog.csdn.net/lulei9876/article/details/39552631