设计模式之---装饰器设计模式

职责:动态的为一个对象增加新的功能

   装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。


实现细节:

——Component抽象构件角色:真实对象和装饰对象有相同的接口。这样,客户端对象就能够以与真实对象相同的方式同装饰对象交互。

——ConcreteComponent具体构件角色(真实对象):io流中的FileInputStream、    FileOutputStream

——Decorator装饰角色:持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。

——ConcreteDecorator具体装饰角色:负责给构件对象增加新的责任。


 开发中的使用场景:

  IO中输入流和输出流的设计

  Swing包中图形界面构件功能

  Servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper类增强了request对象的功能。

  Struts2中,request,response,session对象的处理


 

1. 创建一个抽象组件ICar接口,并创建具体构建角色以及各个具体装饰角色

复制代码
 1 package com.ztq.decorator;
 2 
 3 /***
 4  * 抽象组件
 5  * @author ZTQ
 6  *
 7  */
 8 public interface ICar {
 9     void move();
10 }
11 
12 //ConcreteComponent 具体构件角色(真实对象)
13 class Car implements ICar{
14 
15     @Override
16     public void move() {
17         System.out.println("陆地上跑!");
18     }
19     
20 }
21 
22 class SuperCar implements ICar{
23     private ICar car;
24     public SuperCar(ICar car){
25         this.car = car;
26     }
27     
28     @Override
29     public void move() {
30         car.move();
31     }
32     
33 }
34 
35 //ConcreteDecorator具体装饰角色
36 class FlyCar extends SuperCar{
37 
38     public FlyCar(ICar car) {
39         super(car);
40     }
41     
42     public void fly(){
43         System.out.println("天上飞");
44     }
45     
46     @Override
47     public void move() {
48         super.move();
49         fly();
50     }
51 }
52 
53 //ConcreteDecorator具体装饰角色
54 class WaterCar extends SuperCar{
55 
56     public WaterCar(ICar car) {
57         super(car);
58     }
59     
60     public void swim(){
61         System.out.println("水里游");
62     }
63     
64     @Override
65     public void move() {
66         super.move();
67         swim();
68     }
69 }
70 
71 //ConcreteDecorator具体装饰角色
72 class AICar extends SuperCar{
73 
74     public AICar(ICar car) {
75         super(car);
76     }
77     
78     public void autoMove(){
79         System.out.println("自动跑");
80     }
81     
82     @Override
83     public void move() {
84         super.move();
85         autoMove();
86     }
87 }
复制代码

 

2. 创建测试类Client

复制代码
 1 package com.ztq.decorator;
 2 
 3 public class Client {
 4     public static void main(String[] args) {
 5         Car car = new Car();
 6         car.move();
 7         
 8         System.out.println("增加新的功能:飞行");
 9         FlyCar flycar = new FlyCar(car);
10         flycar.move();
11         
12         System.out.println("增加新的功能:水里游");
13         WaterCar waterCar = new WaterCar(car);
14         waterCar.move();
15         
16         System.out.println("增加两个新的功能,飞行,水里游");
17         WaterCar waterCar2 = new WaterCar(new FlyCar(car));
18         waterCar2.move();
19     }
20 }
复制代码

 

结果:

复制代码
陆地上跑!
增加新的功能:飞行
陆地上跑!
天上飞
增加新的功能:水里游
陆地上跑!
水里游
增加两个新的功能,飞行,水里游
陆地上跑!
天上飞
水里游
复制代码

 

UML图:

 


 

总结:

  装饰模式(Decorator)也叫包装器模式(Wrapper)

  装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。

  优点:

  • 扩展对象功能,比继承灵活,不会导致类个数急剧增加
  • 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象
  • 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类

  缺点:

  • 产生很多小对象。大量小对象占据内存,一定程度上影响性能
  • 装饰模式易于出错,调试排查比较麻烦

 

装饰模式和桥接模式的区别:

两个模式都是为了解决过多子类对象问题。但他们的诱因不一样。桥接模式是对象自身现有机制沿着多个维度变化,是既有部分不稳定。装饰模式是为了增加新的功能。

 

posted @ 2018-09-02 16:19  后知、后觉  阅读(319)  评论(0编辑  收藏  举报