装饰模式(Decorator Pattern),也称为包装模式(Wrapper Pattern)指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

咱这么说:

  比如说,我要设计一个咖啡厅订单管理项目, 订单肯定包括 咖啡的种类和一些配料,如果我设计一个抽象类,让所有这些东西都去继承他,那肯定会引起类爆炸,自己以后想往里添加新的咖啡类型和配料,你都有可能找不到,影响拓展性,不方便改动和维护,就行这样,多麻烦, [23种设计模式]---装饰者模式(1)

第二种优化是咖啡我一定要但是配料,像什么牛奶冰块,巧克力我可以选择不要,就喝咖啡,这时我们就想到,把配料变成boolean类型,如果是0了我代表我不要,1代表我要,但是这么做有一点不好,有的顾客说,老板 ! 加两份牛奶,一份冰,这是就不可以了

 装饰者模式来了!

  这么说吧,装饰者模式就像打包一个快递,把你想要的东西一层一层的包进去,就像俄罗斯套娃一样,要什么就往里放,邮走之后,在那边打开的时候,就用递归的方式,一层一层给它拆开,

  比如说,老板!我要一个无糖咖啡,一份奶,两份冰,安排一下!

[23种设计模式]---装饰者模式(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,里面英文随便打,有小写可以,大小写混合也可以,全大写,那你就左走右走把

[23种设计模式]---装饰者模式(1)

 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 没问题! 今天就到这了,下课!

如有错误一定要联系我更改,初出茅庐,有些不懂请见谅!