关于设计模式:装饰器模式让你的对象变得更强大

86次阅读

共计 4994 个字符,预计需要花费 13 分钟才能阅读完成。

在日常开发中,当须要给一个现有类增加附加职责,而又不能采纳生成子类的办法进行裁减时。例如,该类被暗藏或者该类是终极类或者采纳继承形式会产生大量的子类。这时候,咱们该怎么办呢?咱们能够应用装璜器器模式来解决这个问题, 本文将从以下四个方面解说装璜器器模式

  • 简介
  • 优缺点
  • 利用场景
  • Java 代码示例、
  • Spring 代码示例

简介

装璜器模式(Decorator Pattern)是一种结构型设计模式,它能够在不扭转现有对象的构造的状况下,动静地给对象减少一些额定的性能。装璜器模式通过创立一个包装对象(即装璜器)来包裹实在对象,并在放弃实在对象的接口不变的前提下,为其提供额定的性能。装璜器模式能够在运行时依据须要抉择不同的装璜器来组合和批改对象的行为。

  • Component(组件接口):所有被装璜组件及装璜器对应的接口标准,指定进行装璜的行为办法。对应本章例程中的展现接口 Showable。
  • ConcreteComponent(组件实现):须要被装璜的组件,实现组件接口标准,只具备本身未被装璜的原始个性。对应本章例程中的女生类 Girl。
  • Decorator(装璜器):装璜器的高层抽象类,同样实现组件接口标准,且蕴含一个被装璜的组件。
  • ConcreteDecorator(装璜器实现):继承自装璜器抽象类的具体子类装璜器,能够有多种实现,在被装璜组件对象的根底上为其增加新的个性。对应本章例程中的粉底类 FoundationMakeup、口红类 Lipstick。

举荐博主开源的 H5 商城我的项目 waynboot-mall,这是一套全副开源的微商城我的项目,蕴含三个我的项目:经营后盾、H5 商城前台和服务端接口。实现了商城所需的首页展现、商品分类、商品详情、商品 sku、分词搜寻、购物车、结算下单、支付宝 / 微信领取、收单评论以及欠缺的后盾治理等一系列性能。技术上基于最新得 Springboot3.0、jdk17,整合了 MySql、Redis、RabbitMQ、ElasticSearch 等罕用中间件。分模块设计、简洁易保护,欢送大家点个 star、关注博主。

github 地址:https://github.com/wayn111/waynboot-mall

优缺点

装璜器模式的长处有:

  • 装璜器模式是继承的无力补充,比继承灵便,在不扭转原有对象的状况下,动静地给一个对象扩大性能,即插即用。
  • 通过应用不同的装璜器及这些装璜器的排列组合,能够实现不同成果。
  • 装璜器模式齐全恪守开闭准则,能够在不批改原有代码的根底上减少新的性能。

装璜器模式的毛病有:

  • 装璜器模式会减少许多子类,适度应用会减少程序的复杂性。
  • 装璜器模式会减少对象之间的分割,可能会引入循环援用的问题。
  • 装璜器模式会影响对象的标识,当应用装璜器对对象进行包装时,对象的类型和行为可能会发生变化。

利用场景

装璜器模式实用于以下场景:

  • 当须要给一个现有的类增加附加职责,而又不能采纳继承的形式时,能够应用装璜器模式。例如,在不批改原有代码的状况下给一个窗口增加滚动条或者边框等性能。
  • 当须要动静地给一个对象减少性能,而又须要撤销该性能时,能够应用装璜器模式。例如,在电子商务系统中依据用户抉择的不同优惠券来计算商品价格时,能够应用装璜器模式来实现。
  • 当须要为一批兄弟类进行改装或加装性能时,能够应用装璜器模式。例如,在一个图形界面工具箱中为多个不同的组件提供一些公共的性能时,能够应用装璜器模式来实现。

java 代码示例

以下是一个实现装璜器模式的 java 示例代码

  1. 定义了一个形象组件接口 Shape 和两个具体组件类 Circle 和 Rectangle,
// 形象组件接口
public interface Shape {void draw();
}

// 具体组件类:圆形
public class Circle implements Shape {
    @Override
    public void draw() {System.out.println("Drawing a circle");
    }
}

// 具体组件类:矩形
public class Rectangle implements Shape {
    @Override
    public void draw() {System.out.println("Drawing a rectangle");
    }
}
  1. 定义一个形象装璜器类 ShapeDecorator 和两个具体装璜器类 RedShapeDecorator 和 GreenShapeDecorator,
// 形象装璜器类
public abstract class ShapeDecorator implements Shape {
    // 持有一个形象组件对象
    protected Shape shape;

    // 构造方法
    public ShapeDecorator(Shape shape) {this.shape = shape;}

    // 调用被包装对象的办法
    @Override
    public void draw() {shape.draw();
    }
}

// 具体装璜器类:红色装璜器
public class RedShapeDecorator extends ShapeDecorator {
    // 构造方法
    public RedShapeDecorator(Shape shape) {super(shape);
    }

    // 重写 draw 办法,在调用被包装对象的办法之前或之后增加新的性能
    @Override
    public void draw() {
        // 调用被包装对象的办法
        super.draw();
        // 增加新的性能
        setRedBorder();}

    // 定义新的性能办法
    private void setRedBorder() {System.out.println("Setting red border");
    }
}

// 具体装璜器类:绿色装璜器
public class GreenShapeDecorator extends ShapeDecorator {
    // 构造方法
    public GreenShapeDecorator(Shape shape) {super(shape);
    }

    // 重写 draw 办法,在调用被包装对象的办法之前或之后增加新的性能
    @Override
    public void draw() {
        // 调用被包装对象的办法
        super.draw();
        // 增加新的性能
        setGreenBorder();}

    // 定义新的性能办法
    private void setGreenBorder() {System.out.println("Setting green border");
    }
}
  1. 编写装璜器模式测试代码,main 函数中创立了不同的组件和装璜器对象,并调用了它们的办法,
// 测试类
public class DecoratorPatternDemo {public static void main(String[] args) {
        // 创立一个圆形对象
        Shape circle = new Circle();
        // 创立一个矩形对象
        Shape rectangle = new Rectangle();
        // 创立一个红色装璜器对象,包装圆形对象
        Shape redCircle = new RedShapeDecorator(circle);
        // 创立一个绿色装璜器对象,包装矩形对象
        Shape greenRectangle = new GreenShapeDecorator(rectangle);

        // 调用各个对象的办法,展现不同的成果
        System.out.println("Normal circle:");
        circle.draw();
        System.out.println("Normal rectangle:");
        rectangle.draw();
        System.out.println("Red circle:");
        redCircle.draw();
        System.out.println("Green rectangle:");
        greenRectangle.draw();}
}

输入后果如下:

Normal circle:
Drawing a circle
Normal rectangle:
Drawing a rectangle
Red circle:
Drawing a circle
Setting red border
Green rectangle:
Drawing a rectangle
Setting green border

Spring 代码示例

要想再 Spring 我的项目中利用装璜器模式,只需对以上代码进行简略革新即可,

  1. 给具体组件类 Circle、Rectangle 增加 @Component 注解,
@Component
public class Rectangle implements Shape {
    @Override
    public void draw() {System.out.println("Drawing a rectangle");
    }
}

@Component
public class Rectangle implements Shape {
    @Override
    public void draw() {System.out.println("Drawing a rectangle");
    }
}
  1. 给具体装璜器类 RedShapeDecorator 和 GreenShapeDecorator 类增加 @Component 注解,
@Component
public class GreenShapeDecorator extends ShapeDecorator {
    // 构造方法
    public GreenShapeDecorator(@Qualifier("rectangle") Shape shape) {super(shape);
    }

    // 重写 draw 办法,在调用被包装对象的办法之前或之后增加新的性能
    @Override
    public void draw() {
        // 调用被包装对象的办法
        super.draw();
        // 增加新的性能
        setGreenBorder();}

    // 定义新的性能办法
    private void setGreenBorder() {System.out.println("Setting green border");
    }
}

@Component
public class RedShapeDecorator extends ShapeDecorator {
    // 构造方法
    public RedShapeDecorator(@Qualifier("circle") Shape shape) {super(shape);
    }

    // 重写 draw 办法,在调用被包装对象的办法之前或之后增加新的性能
    @Override
    public void draw() {
        // 调用被包装对象的办法
        super.draw();
        // 增加新的性能
        setRedBorder();}

    // 定义新的性能办法
    private void setRedBorder() {System.out.println("Setting red border");
    }
}
  1. 编写 Spring 我的项目测试代码,
@SpringBootTest
@RunWith(SpringRunner.class)
public class DecoratorTest {

    // 从 Spring 容器中获取 Context 对象
    @Autowired
    private RedShapeDecorator redCircle;
    @Autowired
    private GreenShapeDecorator greenRectangle;

    @Test
    public void test() {System.out.println("Red circle:");
        redCircle.draw();
        System.out.println("Green rectangle:");
        greenRectangle.draw();}
}

输入后果如下:

Red circle:
Drawing a circle
Setting red border
Green rectangle:
Drawing a rectangle
Setting green border

总结

装璜器模式能够将不同性能的单个模块布局至不同的装璜器类中,各装璜器类独立自主,各司其职。客户端能够依据本人的需要自在搭配各种装璜器,每加一层装璜就会有新的个性体现进去,奇妙的设计让功能模块层层叠加,装璜之上套装璜,最终使原始对象的个性动静地失去加强。

关注公众号【waynblog】每周分享技术干货、开源我的项目、实战经验、国外优质文章翻译等,您的关注将是我的更新能源!

正文完
 0