首页 > 其他分享 >设计模式---装饰器模式

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

时间:2022-11-08 00:33:49浏览次数:59  
标签:Style void style public --- class println 设计模式 装饰

简述

运行时,为原对象拓展新的行为。

相较于传统的继承来拓展新的行为,装饰器模式更为的灵活多变,当然实现起来也更为复杂。

话不多说,看个优化案例吧。

优化案例

最初版v0

现有系统中有设定窗口Style的模块,现在想增加一个圆角的样式。以下是现有模块的代码。

class Style {
    public void style() {
        System.out.println("设置Order");
    }
}

第一种传统的修改方式。

class Style {
    public void style() {
        System.out.println("设置Order");
        System.out.println("设置Radius");
    }
}

虽然代码简单,但细想一下,如果我们日后仍然需要单独设置Order的样式怎么办。现在的代码实现已经无法满足了不是?

为此,我们可能会想到另一种方案。使用继承。

class BaseStyle {
    public void style() {
        System.out.println("设置Order");
    }
}
class Radius extends BaseStyle {
    public void style() {
        super.style();
        System.out.println("设置Radius");
    }
}

确实,如果不在意类的命名的话,目前来看这确实是个好的选择。请注意,只是目前来看。设计不只着眼与当前,而是需要放眼未来。什么意思呢?比如,当未来需要添加一个Color样式的时候怎么办,有人可能认为添加再添加一个BassStyle类的子类Color就好了;如果客户就只要一个单独的Color样式呢,或者说需要一个可以设置Radius和Color的样式。再超前一些,客户如果想要的是增加一个样式,且可以与现有的任何一种或多种样式随意组合呢?又该怎么办?传统的继承已经搞不了了呀。

别慌,最后这一种需求正好就是使用装饰器模式的目的。我们来看看改进后的案例吧。

修改版v1

使用装饰器模式优化上述需求,使得任意样式间可以任意组合,这种任意组合包括任意种类和数量。

public interface Style {
    void style();
}
public class Order implements Style {
    @Override
    public void style() {
        System.out.println("设置Order");
    }
}
public class Radius implements Style {
    @Override
    public void style() {
        System.out.println("设置Radius");
    }
}

public class Color implements Style {
    @Override
    public void style() {
        System.out.println("设置Color");
    }
}
public class OrderDecorator implements Style {
    private Style style;
    public OrderDecorator(Style target) {
        this.style = target;
    }
    @Override
    public void style() {
        style.style();
        decorator();
    }
    private void decorator() {
        System.out.println("设置Order");
    }
}
public class RadiusDecorator implements Style {
    private Style style;
    public RadiusDecorator(Style target) {
        this.style = target;
    }
    @Override
    public void style() {
        style.style();
        decorator();
    }
    private void decorator() {
        System.out.println("设置Radius");
    }
}
public class ColorDecorator implements Style {
    private Style style;
    public ColorDecorator(Style target) {
        this.style = target;
    }
    @Override
    public void style() {
        style.style();
        decorator();
    }
    private void decorator() {
        System.out.println("设置Color");
    }
}

定义三个装饰器类:OrderDecorator, RadiusDecorator, ColorDecorator分别实现Style接口,定义decorator方法用(动态拓展的核心方法之一)。调用完``targetstyle方法后调用decorator`方法实现功能的动态拓展。接着,看看客户端如何使用。

public class Client {
    public static void main(String[] args) {
        Style style = new Order();
        Style style1 = new ColorDecorator(style);
        Style style2 = new RadiusDecorator(style1);
        style2.style();
    }
}

输出结果:

设置Order
设置Color
设置Radius

修改版v2

上述优化可以看到一些重复冗余的代码,还有再次优化的空间。以下是实现样例。

public interface Style {
    void style();
}
public class Order implements Style {
    @Override
    public void style() {
        System.out.println("设置Order");
    }
}
public class Radius implements Style {
    @Override
    public void style() {
        System.out.println("设置Radius");
    }
}
public class Color implements Style {
    @Override
    public void style() {
        System.out.println("设置Color");
    }
}
public abstract class StyleDecorator implements Style { // 抽出共通新建装饰类的高层抽象类
    protected Style style;
    public StyleDecorator(Style target) {
        this.style = target;
    }
    @Override
    public void style() { // style设置
        style.style();
        decorator();
    }
    protected abstract void decorator(); // 装饰方法
}
public class OrderDecorator extends StyleDecorator {
    public OrderDecorator(Style target) {
        super(target);
    }
    @Override
    protected void decorator() {
        System.out.println("设置Order");
    }
}
public class RadiusDecorator extends StyleDecorator {
    public RadiusDecorator(Style target) {
        super(target);
    }
    @Override
    protected void decorator() {
        System.out.println("设置Radius");
    }
}
public class ColorDecorator extends StyleDecorator {
    public ColorDecorator(Style target) {
        super(target);
    }
    @Override
    protected void decorator() {
        System.out.println("设置Color");
    }
}

客户端的使用和输出结果还是和v1一样。

public class Client {
    public static void main(String[] args) {
        Style style = new Order();
        Style style1 = new ColorDecorator(style);
        Style style2 = new RadiusDecorator(style1);
        style2.style();
    }
}

输出结果:

设置Order
设置Color
设置Radius

新建高层抽象类,讲冗余的方法属性都打包到抽象类中,减少重复的代码。
这个应该属于题外话了,可以见得设计模式的实现方式是多种多样的。不要过度拘泥于模板。只要能达成目的,想怎么设计就可以怎么设计。

修改版v1和v2都是装饰器模式,实际开发根据需求斟酌即可。

总结

优点

  1. 开发时可以自由组合各种各样的功能。
  2. 新增的功能对于现有功能没有任何的影响。

缺点

  1. 增加系统的复杂度。
  2. 对于开发人员的技术要求提高。

应用场景

  1. 需要灵活组合功能的场合。
  2. 限制继承,但又想拓展类的功能的场合。

标签:Style,void,style,public,---,class,println,设计模式,装饰
From: https://www.cnblogs.com/spoonb/p/16731658.html

相关文章

  • 《数论女王-数论与算法的奇幻故事》知识点
    目录约数、素数、合数(第一章)素因数分解(第一章、第二章)盈数、亏数、完满数(第二章)亲和数斐波那契数列(第三章、第五章)费马小定理、伪素数、卡迈克尔数(第六章)素数的生成算式(第......
  • vite配合element-plus并配置vite.config.js按需加载出现的问题
    一开始项目vite版本是1  然后创建vite.config.js出现模块““vite“”没有导出的成员“defineConfig”  后面就把vite升级到2  升级完之后跑项目出现这个问......
  • 洛谷-P2491 消防
    消防树上直径+尺取考虑答案的路径一定是在树上直径,因为离树上任意一个点最远的点一定是直径的两个点其中之一因此先\(dfs\)一下找出直径两个端点从其中一个端点出......
  • python课本学习-第一章
    chapter1python开发入门1、python之父:GuidovanRossum2、python语言的特征:简单易学免费&开源可移植性解释性面向对象在面向对象的语言中,程序是......
  • JS数据结构与算法-队列结构
    队列结构一.认识队列受限的线性结构:我们已经学习了一种受限的线性结构:栈结构.并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的效果.下面,我们再......
  • grafana agent 配置支持faro-web-sdk试用
    faro-web-sdk对于grafana周边的使用属于一个all-in-one模式的,都是通过grafanaagent进行转发处理的参考架构  实际玩法实际上并不是需要grafancloud,实际上基于......
  • 洛谷--【P1618】三连击升级版题解 排列枚举+循环枚举+stl
    题目描述将 1,2,…,91,2,…,9 共 99 个数分成三组,分别组成三个三位数,且使这三个三位数的比例是 A:B:C,试求出所有满足条件的三个三位数,若无解,输出 No!!!。输入格式......
  • MySql -基础学习2- 创建数据库表
    CREATETABLEIFNOTEXISTS`stdent`(`id`INT(4)NOTNULLAUTO_INCREMENTCOMMENT'学员id',`name`VARCHAR(30)NOTNULLDEFAULT'匿名'COMMENT'姓名',`paw`VA......
  • 【Java复健指南10】OOP高级01-类变量、类方法和main
    类变量什么是类变量类变量也叫静态变量/静态属性,是该类的所有对象共享的变量,任何一个该类的对象去访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改......
  • ArchLinux安装手册(2022-10-01)
    准备工作镜像下载:北京外国语大学镜像使用ventoy做启动盘:(1)ventoy下载:github下载地址(2)解压运行下载好的ventoy,设备选择准备好的U盘(会清空),然后选择安装即可。......