zoukankan      html  css  js  c++  java
  • java设计模式之--装饰者模式

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
    这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
    我们通过下面的实例来演示装饰器模式的用法。其中,我们将把一个形状装饰上不同的颜色,同时又不改变形状类。

    1、意图

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

    2、适用环境

    1. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责
    2. 处理那些可以撤销的职责
    3. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类的数量爆炸增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

    3、关键代码

    1. Component 类充当抽象角色,不应该具体实现。
    2. 修饰类引用和继承 Component 类,具体扩展类重写父类方法。

    应用实例

    1、孙悟空有 72 变,当他变成"庙宇"后,他的根本还是一只猴子,但是他又有了庙宇的功能。 2、不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。

    注意事项:可代替继承。

    4、参与者

    1. Component(抽象构件角色)
      真实对象和装饰对象有相同的接口,这样,客户端对象就能够以与真实对象相同的方式同装饰对象进行交互。
    2. ConcreteComponent(具体构件角色,即真实对象)
      IO流中的FileInputStream、FileOutputStream
    3. Decorator(装饰角色)
      持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象。这样,就能在真实对象调用前后增加新的功能。
    4. ConcreteDecorator(具体装饰角色)
      负责给构件对象增加新的责任。

    5、类图

    6、涉及角色

    1. 抽象组件:定义一个抽象接口,来规范准备附加功能的类。
    2. 具体组件:将要被附加功能的类,实现抽象构件角色接口。
    3. 抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口。
    4. 具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。

    7、代码实现

    一、创建一个接口

    //Shape.java
    public interface Shape {
       void draw();
    }
    

    二、创建实现接口的实体类。

    //Rectangle.java
    public class Rectangle implements Shape {
     
       @Override
       public void draw() {
          System.out.println("Shape: Rectangle");
       }
    }
    //Circle.java
    public class Circle implements Shape {
     
       @Override
       public void draw() {
          System.out.println("Shape: Circle");
       }
    }
    

    三、创建实现了 Shape 接口的抽象装饰类。

    //ShapeDecorator.java
    public abstract class ShapeDecorator implements Shape {
       protected Shape decoratedShape;
     
       public ShapeDecorator(Shape decoratedShape){
          this.decoratedShape = decoratedShape;
       }
     
       public void draw(){
          decoratedShape.draw();
       }  
    }
    

    四、创建扩展了 ShapeDecorator 类的实体装饰类。

    //RedShapeDecorator.java
    public class RedShapeDecorator extends ShapeDecorator {
     
       public RedShapeDecorator(Shape decoratedShape) {
          super(decoratedShape);     
       }
     
       @Override
       public void draw() {
          decoratedShape.draw();         
          setRedBorder(decoratedShape);
       }
     
       private void setRedBorder(Shape decoratedShape){
          System.out.println("Border Color: Red");
       }
    }
    

    五、使用 RedShapeDecorator 来装饰 Shape 对象。

    public class DecoratorPatternDemo {
       public static void main(String[] args) {
     
          Shape circle = new Circle();
          ShapeDecorator redCircle = new RedShapeDecorator(new Circle());
          ShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
          //Shape redCircle = new RedShapeDecorator(new Circle());
          //Shape redRectangle = new RedShapeDecorator(new Rectangle());
          System.out.println("Circle with normal border");
          circle.draw();
     
          System.out.println("
    Circle of red border");
          redCircle.draw();
     
          System.out.println("
    Rectangle of red border");
          redRectangle.draw();
       }
    }
    

    六、执行程序,输出结果

    Circle with normal border
    Shape: Circle
    
    Circle of red border
    Shape: Circle
    Border Color: Red
    
    Rectangle of red border
    Shape: Rectangle
    Border Color: Red
    

    8、优缺点

    1. 优点

    装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。

    2. 缺点

    多层装饰比较复杂。

    3. 实际使用

    这里我们说一下,在java中I/O便使用了装饰者模式。

    4. 装饰者用到的设计原则:

    1. 多用组合,少用继承。
    2. 对扩展开放,对修改关闭。
  • 相关阅读:
    STM32 F4 DAC DMA Waveform Generator
    STM32 F4 General-purpose Timers for Periodic Interrupts
    Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式
    Python第十三天 django 1.6 导入模板 定义数据模型 访问数据库 GET和POST方法 SimpleCMDB项目 urllib模块 urllib2模块 httplib模块 django和web服务器整合 wsgi模块 gunicorn模块
    查看SQL Server服务运行帐户和SQL Server的所有注册表项
    Pycharm使用技巧(转载)
    SQL Server 2014内存优化表的使用场景
    Python第十天 print >> f,和fd.write()的区别 stdout的buffer 标准输入 标准输出 从控制台重定向到文件 标准错误 重定向 输出流和输入流 捕获sys.exit()调用 optparse argparse
    Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
    Python第六天 类型转换
  • 原文地址:https://www.cnblogs.com/coldfirecx/p/14269700.html
Copyright © 2011-2022 走看看