[23种设计模式]---装饰者模式(1)
装饰者官方说:
装饰模式(Decorator Pattern),也称为包装模式(Wrapper Pattern)指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
咱这么说:
比如说,我要设计一个咖啡厅订单管理项目, 订单肯定包括 咖啡的种类和一些配料,如果我设计一个抽象类,让所有这些东西都去继承他,那肯定会引起类爆炸,自己以后想往里添加新的咖啡类型和配料,你都有可能找不到,影响拓展性,不方便改动和维护,就行这样,多麻烦,
第二种优化是咖啡我一定要但是配料,像什么牛奶冰块,巧克力我可以选择不要,就喝咖啡,这时我们就想到,把配料变成boolean类型,如果是0了我代表我不要,1代表我要,但是这么做有一点不好,有的顾客说,老板 ! 加两份牛奶,一份冰,这是就不可以了
装饰者模式来了!
这么说吧,装饰者模式就像打包一个快递,把你想要的东西一层一层的包进去,就像俄罗斯套娃一样,要什么就往里放,邮走之后,在那边打开的时候,就用递归的方式,一层一层给它拆开,
比如说,老板!我要一个无糖咖啡,一份奶,两份冰,安排一下!
程序代码:
饮品定义为抽象类,定义商品和价格,有一个抽象方法cost(),记录总花费
1 package learn.Decorate.Decorate_L; 2 3 public abstract class Drink { 4 public String decoration=""; 5 private float price; 6 7 public String getDecoration() { 8 return decoration+"-"+this.price; 9 } 10 11 public void setDecoration(String decoration) { 12 this.decoration = decoration; 13 } 14 15 public float getPrice() { 16 return price; 17 } 18 19 public void setPrice(float price) { 20 this.price = price; 21 } 22 public abstract float cost(); 23 }
我们创建俩个类(Decorator和Coffee)分别继承Drink类,为什么这么麻烦呢,因为你会点一份咖啡配上多个配料(牛奶,冰),不会点两个咖啡,要一份配料,这里的两个类分别代表主品咖啡和配料.
1 package learn.Decorate.Decorate_L; 2 3 public class Coffee extends Drink { 4 @Override 5 public float cost() { 6 return super.getPrice(); 7 } 8 }
1 package learn.Decorate.Decorate_L; 2 //注意这里,它是一层一层往里包裹的, 3 public class Decorator extends Drink { 4 private Drink obj; 5 6 public Decorator(Drink obj) { 7 this.obj = obj; 8 } 9 10 @Override 11 public float cost() { 12 return super.getPrice()+obj.cost(); 13 } 14 15 public String getDecoration(){ 16 return super.getDecoration()+"&&"+obj.getDecoration(); 17 } 18 }
无糖咖啡来了!
1 package learn.Decorate.Decorate_L; 2 3 public class Delcoff extends Coffee { 4 public Delcoff() { 5 super.setDecoration("Delcoff无糖咖啡"); 6 super.setPrice(12.5f); 7 } 8 }
ShortBlack咖啡来了
1 package learn.Decorate.Decorate_L; 2 3 public class ShortBlack extends Coffee { 4 public ShortBlack() { 5 super.setDecoration("ShortBlack咖啡"); 6 super.setPrice(14.5f); 7 } 8 }
冰块,它来了,它来了!
1 package learn.Decorate.Decorate_L; 2 3 public class Ice extends Decorator { 4 public Ice(Drink obj) { 5 super(obj); 6 super.setDecoration("加冰"); 7 super.setPrice(0.8f); 8 } 9 }
牛的奶,嘎嘎纯的牛奶来了!
1 package learn.Decorate.Decorate_L; 2 3 public class Mike extends Decorator { 4 public Mike(Drink obj) { 5 super(obj); 6 super.setDecoration("加奶"); 7 super.setPrice(3.2f); 8 } 9 }
开始点菜,老板!我要一份ShortBlack咖啡,再给我旁边不认识的小姐姐来一份无糖咖啡,加一份奶,两份冰.
1 package learn.Decorate.Decorate_L; 2 3 public class CoffeeTest { 4 public static void main(String[] args) { 5 Drink order; 6 order = new ShortBlack(); 7 System.out.println("订单1包括:"+order.getDecoration()); 8 System.out.println("总价:"+order.cost()); 9 System.out.println("----------------------"); 10 11 order = new Delcoff(); 12 order = new Mike(order); 13 order = new Ice(order); 14 order = new Ice(order); 15 System.out.println("订单2包括:"+order.getDecoration()); 16 System.out.println("总价:"+order.cost()); 17 } 18 }
没毛病出来跑两圈,!!!
1 订单1包括:ShortBlack咖啡-14.5 2 总价:14.5 3 ---------------------- 4 订单2包括:加冰-0.8&&加冰-0.8&&加奶-3.2&&Delcoff无糖咖啡-12.5 5 总价:17.3 6 7 Process finished with exit code 0
拓展一下,无意中我发现IO的工作原理也是这样,被来要把源码都扒下来分析一下的,刚才接到一个面试电话让我下午面试,就不说了,放张图,有兴趣的自己研究一下,我放一个调用内置的装饰者模式的简单项目吧,就是把你txt文件中的大小写变成大写
1 package learn.Decorate.UpperCaseInputStream; 2 3 import java.io.FilterInputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 7 public class UpperCaseInputStream extends FilterInputStream { 8 /** 9 * Creates a <code>FilterInputStream</code> 10 * by assigning the argument <code>in</code> 11 * to the field <code>this.in</code> so as 12 * to remember it for later use. 13 * 14 * @param in the underlying input stream, or <code>null</code> if 15 * this instance is to be created without an underlying stream. 16 */ 17 protected UpperCaseInputStream(InputStream in) { 18 super(in); 19 } 20 21 public int read() throws IOException { 22 int c = super.read(); 23 return c == -1 ? c : Character.toUpperCase((char) (c)); 24 } 25 26 33 }
在桌面上自己建立一个huang.txt,里面英文随便打,有小写可以,大小写混合也可以,全大写,那你就左走右走把
1 package learn.Decorate.UpperCaseInputStream; 2 3 import java.io.*; 4 5 public class InputTest { 6 public static void main(String[] args) { 7 int c; 8 try { 9 InputStream in = new UpperCaseInputStream(new BufferedInputStream(new FileInputStream("C:\\Users\\Jerry\\Desktop\\huang.txt"))); 10 while ((c = in.read())>=0){ 11 System.out.print((char)c); 12 } 13 } catch (IOException e) { 14 e.printStackTrace(); 15 } 16 } 17 }
运行一下:
1 THIS IS A BOOK 2 Process finished with exit code 0
ok 没问题! 今天就到这了,下课!
如有错误一定要联系我更改,初出茅庐,有些不懂请见谅!