装饰者模式(Decorator)

1.装饰者模式:

    就是用来装饰别的类的,可以理解成 加油添醋(或锦上添花····)

    就像人一样,人就是原来的类,每一个装饰类就如一件件的衣服,可以根据需求随意组合的穿到人的身上。

    例子:

          面条,可以是牛肉面瘦肉面、·····等等,

          转换成java代码就是:

              面条 --- 抽象类 Noodle;

             牛肉面 ----  BeefNoodles;

             瘦肉面  ---- MeatNoodles;    

     ```````````这样就会有各种各样的面条的具体类了,

     关键不是数量的问题,假如有一个 加鸡蛋的牛肉面呢? 再新建一个 BeefAndEggNoodles?    

     那么,如果顾客的要求更多一点呢 加蛋加香肠的牛肉面呢·······················    

  

     应该怎么办呢,其实我们应该分清楚主次,很明显这里主体是牛肉面/瘦肉面,装饰的是配料(什么鸡蛋,香肠,香菜等·····),

     而且这些配料还有可能随意组合的,所以按配料来定义一个面条对象是不理智的。

    首先,先创建一个Noodle抽象类,这个没问题吧:

 1 package design.patterns.decorator;

 2 

 3 public abstract class Noodle {

 4    //描述,说明这是什么面

 5    public String description;

 6    

 7    public String getDescription(){

 8        return description;

 9    }

10    

11    //吃后感

12    public abstract String feeling();

13 }
View Code

   然后创建一个继承了Noodle类的 牛肉面类BeefNoodle

(可能有人会问,为什么鸡蛋,香肠这些才是配料,而牛肉不也是加在面里面的吗,牛肉应该也算是配料的一种啊;这里只是相对而言,因为相对于一个香肠,那些牛肉就已经不算是配料了,

 又例如蛋糕,巧克力蛋糕、冰激凌蛋糕、还有花瓣以及卡片,相对而言,花瓣和卡片才算是装饰,巧克力和冰激凌则应该认为是蛋糕的一部分了,当然这个标准你可以自己拿捏)

 1 package design.patterns.decorator;

 2 

 3 public class BeefNoodle extends Noodle{

 4     public BeefNoodle(){

 5         this.description = "这是一碗牛肉面";    

 6     }

 7     

 8     @Override

 9     public String feeling() {

10         return "牛肉面就是香。";

11     }

12 

13 }
View Code

 在还没有加其他配料前就先直接测试一下吧:TestNoodle

1 package design.patterns.decorator;

2 

3 public class TestNoodle {

4     public static void main(String[] args){

5         //这是普通的牛肉面。

6         Noodle noodle = new BeefNoodle();

7         System.out.println(noodle.feeling());

8     }

9 }
View Code

  结果如下:

           装饰者模式(Decorator)

 

   重点来了,关键来了,定义一个面条配料类NoodleDecorator

(因为这只是配料,可以理解为"加了·····配料的·····面",如:"加了 蛋 的 牛肉面",但这种面并不是真实存在的(不像牛肉面那么具体),所以声明为抽象类)

 1 package design.patterns.decorator;

 2 

 3 public abstract class NoodleDecorator extends Noodle{

 4     //同时它也是继承了Noodle,跟各种面是同一父类的,所以在多态上会更便利

 5     //这一步是关键,使用了组合,把"被装饰者"传进来让"装饰者"进行"装饰(包装,所谓的加油添醋)"

 6     public Noodle noodle;

 7     

 8     public NoodleDecorator(Noodle n){

 9         noodle = n;

10     }

11     @Override

12     public abstract String feeling() ;

13 }
View Code

 然后创建具体的装饰类,加蛋的配料面条类 AddEgg:

 1 package design.patterns.decorator;

 2 

 3 public class AddEgg extends NoodleDecorator{

 4 

 5     public AddEgg(Noodle n) {

 6         super(n);

 7     }

 8     

 9     @Override

10     public String feeling() {

11         return this.noodle.getDescription() +" +加了蛋才是最美味。";

12     }

13 

14 }
View Code

 再创建一个 加了香肠的类 AddSuasage

 1 package design.patterns.decorator;

 2 

 3 public class AddSausage extends NoodleDecorator{

 4 

 5     public AddSausage(Noodle n) {

 6         super(n);

 7     }

 8 

 9     @Override

10     public String feeling() {

11         return this.noodle.feeling() +" +加一根香肠后,更加回味无穷。";

12     }

13 

14 }
View Code

   好了,现在来开始装饰吧:

 1 package design.patterns.decorator;

 2 

 3 public class TestNoodle {

 4     public static void main(String[] args){

 5         //这是普通的牛肉面。

 6         Noodle noodle = new BeefNoodle();

 7         System.out.println(noodle.feeling());

 8         

 9         //老板,给我来晚加蛋的牛肉面

10         Noodle n1 = new AddEgg(new BeefNoodle());

11         System.out.println(n1.feeling());

12         

13         //老板,给我来晚加香肠的牛肉面

14         Noodle n2 = new AddSausage(new BeefNoodle());

15         System.out.println(n2.feeling());

16         

17         //加蛋 又加香肠的 牛肉面

18         Noodle n3 = new AddSausage(new AddEgg(new BeefNoodle()));

19         System.out.println(n3.feeling());

20     }

21 }
View Code

    如果这个测试类看着不爽,那就看这个吧:

 1 package design.patterns.decorator;

 2 

 3 public class TestNoodle {

 4     public static void main(String[] args){

 5         //这是普通的牛肉面。

 6         Noodle noodle = new BeefNoodle();

 7         System.out.println(noodle.feeling());

 8         

 9         //没蛋不好吃,在牛肉面的基础上加个蛋

10         noodle = new AddEgg(noodle);

11         System.out.println(noodle.feeling());

12         

13         //既然蛋都加了,再加跟香肠吧

14         noodle = new AddSausage(noodle);

15         System.out.println(noodle.feeling());

16     }

17 }
View Code

 

 结果如下图:

       装饰者模式(Decorator)

  

     总结一下:1. 什么时候用装饰者模式,当类的属性中存在很明显的主次关系,同时这些属性还有可能随意组合,就把那些作为装饰的属性以组合的方式动态添加到类中

                     2. 在Java的IO中,最常见的装饰者模式就是 BufferedInputStream bin = new BufferedInputStream(InputStream);

                        这里,buffer也是以组合的方式"装饰(添加到)"普通的inputStream中的

                    3. 缺点,所有的设计模式都共有的,类的数量增加了,每多一个装饰功能,就得新增一个装饰类;同时逻辑上复杂了不少,理解有一定难度。

你可能感兴趣的:(Decorator)