zoukankan      html  css  js  c++  java
  • 结构型模式

    装饰器模式(Decorator Pattern)

    简介

    装饰器模式允许向一个现有的对象添加新的功能,同时又不改变其结构

    意图

    动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

    特点

    主要解决:为扩展一个类经常使用继承方式,由于继承为类引入静态特征,并且随着扩展功能增多,子类会膨胀。
    何时使用:不想增加很多子类的情况下扩展类。
    如何解决:将具体功能职责划分,同时继承装饰者模式。

    关健代码:

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

    装饰器模式有个特点,就是Decorator对外却拥有与Component同样的接口,而且Component无需知道Decorator存在。装饰类主要用于修饰原有类的核心职责或行为,

    装饰器模式 vs 桥接模式

    桥接模式和装饰器模式,都是在原有类的基础上,为客户端提供新功能,那么它们有什么区别呢?

    1. 新功能
      桥接模式是多个维度变量独立变化,如果新增维度变量,就需要修改原来的类;
      而装饰器模式是原来的类本质(接口、属性)不变,通过修改装饰器模式添加新功能。

    2. 适用场景
      桥接模式适合新增一种多维度变量的组合,例如原来是红色矩形,颜色、形状 2个维度独立变量,现在增加绿色三角形,橙色圆形,就很适合用桥接模式;
      装饰器模式非常适合用来扩展第三方库、类,为原有类、模块添加新的非核心功能。

    装饰器模式 vs 适配器模式

    装饰器模式和适配器模式,都可以对第三方库进行扩展,有什么区别?
    装饰器模式更倾向于在原有类基础上,为原有的类添加新功能。装饰器模式添加了新功能,而且不必关心使用者需要何种接口,更关心能装饰出何种功能。
    适配器模式更倾向于使原来不能一起工作的类,改变接口,让它们一起工作。适配器模式没有添加新功能,而且不得不关注双方需要、提供何种接口。

    应用场景

    1. 假设有一个String类有随机访问其中某个字符charAt()和deleteAt()等接口,但是现在需要将String当做一个栈来用,就需要实现push, pop 接口功能,就可以利用装饰器模式,在原来API基础上实现新功能而改变原有的类;
    2. 孙悟空有72变,当他变成“庙宇”后,根本还是一只猴子,但是又有庙宇的功能。
    3. 不论一幅画有没有画框,都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。

    UML类图

    实现代码

    1. 创建待扩展的接口Shape
    //Shape.java
    public interface Shape {
          public void draw();
    }
    
    1. 创建Shape接口的实体类Circle, Retangle
    // Circle.java
    public class Circle implements Shape {
          @Override
          public void draw() {
                System.out.println("Shape: Circle");
          }
    }
    // Retangle.java
    public class Retangle implements Shape {
          @Override
          public void draw() {
                System.out.println("Shape: Retangle");
          }
    }
    
    1. 创建实现了Shape接口的抽象装饰器类
    // ShapeDecorator.java
    public abstract class ShapeDecorator {
          protected Shape shape;
          
          public ShapeDecorator(Shape shape) {
                this.shape = shape;
          }
          
          public void draw() {
                shape.draw();
          }
    }
    
    1. 创建扩展了ShapeDecorator的实体装饰类RedShapeDecorator
    // RedShapeDecorator.java
    public class RedShapeDecorator extends ShapeDecorator {
          public RedShapeDecorator(Shape shape) {
                super(shape);
          }
          @Override
          public void draw() {
                shape.draw();
                setRedBorder();
          }
          
          private void setRedBorder() {
                System.out.println("Border Color: Red");
          }
    }
    
    1. 使用RedShapeDecorator来装饰Shape对象
    // DecoratorPatternDemo.java
    public class DecoratorPatternDemo {
          public static void main(String[] args) {
                Shape circle = new Circle();
                ShapeDecorator redCircle = new RedShapeDecorator(circle);
                ShapeDecorator redRetangle = new RedShapeDecorator(new  Retangle());
                System.out.println("Circle with normal border");
                circle.draw();
                System.out.println("
    Circle with red border");
                redCircle.draw();
                System.out.println("
    Circle with retangle border");
                redRetangle.draw();
          }
    }
    

    运行结果

    Circle with normal border
    Shape: Circle
    Circle with red border
    Shape: Circle
    Border Color: Red
    Circle with retangle border
    Shape: Retangle
    Border Color: Red
    
  • 相关阅读:
    机器学习:以分析红酒口感为例说明交叉验证的套索模型
    机器学习:分类算法性能指标之ROC曲线
    机器学习:最小二乘法实际应用的一个完整例子
    机器学习:Python中如何使用支持向量机(SVM)算法
    机器学习:python中如何使用朴素贝叶斯算法
    机器学习:Python实现lms中的学习率的退火算法
    机器学习:Python实现最小均方算法(lms)
    @Autowired 与@Resource选择(治好你的强迫症)
    @Resource 进行注入bean的过程
    @Autowired 进行注入bean的过程
  • 原文地址:https://www.cnblogs.com/fortunely/p/14267141.html
Copyright © 2011-2022 走看看