前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >跟着GPT学设计模式之装饰者模式

跟着GPT学设计模式之装饰者模式

原创
作者头像
codetrend
发布2024-03-30 16:48:54
810
发布2024-03-30 16:48:54
举报

你好,这里是codetrend专栏“跟着GPT学设计模式”。

说明

装饰者模式是一种结构型设计模式,它允许你在不修改已有对象的情况下,动态地向对象添加额外的功能。装饰者模式通过包装原始对象来扩展其功能,并提供了一种灵活的方式来组合多个装饰器。装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。

使用mermaid绘制的桥接模式类图如下:

代码语言:mermaid
复制
classDiagram
    class Component {
        +operation(): void
    }

    class ConcreteComponent {
        +operation(): void
    }

    class Decorator {
        -component: Component
        +operation(): void
    }

    class ConcreteDecoratorA {
        +operation(): void
        +addedBehavior(): void
    }

    class ConcreteDecoratorB {
        +operation(): void
        +addedState: string
    }

    Component <|-- ConcreteComponent
    Component <|.. Decorator
    Decorator <|-- ConcreteDecoratorA
    Decorator <|-- ConcreteDecoratorB
  • Component(抽象组件):定义了被装饰者和装饰者的共同接口,包含 operation() 方法。
  • ConcreteComponent(具体组件):实现了抽象组件的接口,并提供了具体的操作。
  • Decorator(抽象装饰者):继承了抽象组件,持有一个抽象组件类型的引用,并在其构造函数中接收被包装的具体组件实例。它同时也实现了抽象组件的接口,以便与具体组件保持一致。
  • ConcreteDecorator(具体装饰者):继承了抽象装饰者,并实现了具体的装饰逻辑。它可以通过调用父类的方法来扩展原始行为,并在需要时添加额外的功能。

该示意图中展示了一个简单的装饰者模式示例,其中 ConcreteComponent 是被装饰的对象,而 Decorator 和 ConcreteDecorator 是用于装饰该对象的装饰者。

装饰者模式的工作流程如下:

  • 客户端创建一个具体组件的实例,并根据需要使用抽象装饰者对其进行包装。
  • 抽象装饰者持有一个抽象组件的引用,并在其构造函数中接收被包装的具体组件实例。
  • 抽象装饰者通过调用持有的抽象组件引用来实现共同接口的方法,可以在方法的前后添加额外的功能。
  • 具体装饰者继承抽象装饰者,并实现自己的装饰逻辑。具体装饰者可以通过调用父类的方法来扩展原始行为。

使用装饰者模式的好处是,它允许你动态地向对象添加功能,而无需修改已有代码。它遵循开闭原则,使得系统更灵活且易于扩展。此外,装饰者模式通过组合多个装饰器,可以实现各种不同的组合效果。

应用场景

项目中使用装饰者模式的例子是 Java IO 库中的输入输出流(InputStream 和 OutputStream)。

在 Java IO 中,InputStream 和 OutputStream 是抽象组件,它们定义了读取和写入数据的基本接口。而具体组件则是实现了这些接口的类,例如 FileInputStream 和 FileOutputStream。

使用装饰者模式时,我们可以创建一个抽象装饰者类 FilterInputStream(继承自 InputStream),它持有一个被包装的 InputStream 对象,并通过调用父类的方法来扩展原始行为。

Java IO 中有许多具体装饰者类,例如 BufferedInputStream(用于提供缓冲读取功能)和 DataInputStream(用于读取不同类型的数据)。这些具体装饰者类继承自 FilterInputStream,通过调用父类的方法来扩展原始的读取行为,并在需要时添加额外的功能。

下面是一个简化的示例代码:

代码语言:java
复制
// 抽象组件
public abstract class InputStream {
    public abstract int read();
}

// 具体组件
public class FileInputStream extends InputStream {
    public int read() {
        // 实现读取文件的逻辑
    }
}

// 抽象装饰者
public abstract class FilterInputStream extends InputStream {
    protected InputStream inputStream;

    public FilterInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    public int read() {
        // 调用被装饰的 InputStream 对象的 read() 方法
        return inputStream.read();
    }
}

// 具体装饰者
public class BufferedInputStream extends FilterInputStream {
    public BufferedInputStream(InputStream inputStream) {
        super(inputStream);
    }

    public int read() {
        // 在调用父类的 read() 方法前后添加额外的缓冲读取功能
        // ...
        return super.read();
    }
}

// 举例
public class FileToTextConverter {
    public static void main(String[] args) {
        String filePath = "path/to/your/file.txt"; // 替换为实际的文件路径

        try (FileInputStream fis = new FileInputStream(filePath);
             BufferedInputStream bis = new BufferedInputStream(fis)) {

            StringBuilder sb = new StringBuilder(); // 使用 StringBuilder 储存文本内容

            byte[] buffer = new byte[8192]; // 使用缓冲区进行读取,这里设置为 8KB
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, bytesRead));
            }

            String text = sb.toString(); // 将 StringBuilder 转换为字符串
            
            System.out.println(text); // 打印文件内容
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

编程示例

步骤1:创建抽象组件(Component)

代码语言:java
复制
public interface Beverage {
    String getDescription();
    double getCost();
}

步骤2:创建具体组件(ConcreteComponent)

代码语言:java
复制
public class Espresso implements Beverage {
    public String getDescription() {
        return "Espresso";
    }

    public double getCost() {
        return 1.99;
    }
}

步骤3:创建抽象装饰者(Decorator)

代码语言:java
复制
public abstract class CondimentDecorator implements Beverage {
    protected Beverage beverage;

    public CondimentDecorator(Beverage beverage) {
        this.beverage = beverage;
    }

    public abstract String getDescription();
    public abstract double getCost();
}

步骤4:创建具体装饰者(ConcreteDecorator)

代码语言:java
复制
public class Milk extends CondimentDecorator {
    public Milk(Beverage beverage) {
        super(beverage);
    }

    public String getDescription() {
        return beverage.getDescription() + ", Milk";
    }

    public double getCost() {
        return beverage.getCost() + 0.5;
    }
}
代码语言:java
复制
public class Mocha extends CondimentDecorator {
    public Mocha(Beverage beverage) {
        super(beverage);
    }

    public String getDescription() {
        return beverage.getDescription() + ", Mocha";
    }

    public double getCost() {
        return beverage.getCost() + 0.3;
    }
}

步骤5:使用装饰者模式

代码语言:java
复制
public class App {
    public static void main(String[] args) {
        // 创建一个具体组件对象
        Beverage espresso = new Espresso();

        // 使用装饰者对具体组件进行包装
        Beverage milkEspresso = new Milk(espresso);
        Beverage mochaMilkEspresso = new Mocha(milkEspresso);

        // 进行操作,输出描述和总价格
        System.out.println(mochaMilkEspresso.getDescription());
        System.out.println("Cost: $" + mochaMilkEspresso.getCost());
    }
}

输出结果:

代码语言:txt
复制
Espresso, Milk, Mocha
Cost: $2.79

在上述示例中,我们创建了一个咖啡饮料的例子。Beverage 是抽象组件,Espresso 是具体组件;CondimentDecorator 是抽象装饰者,Milk 和 Mocha 是具体装饰者。通过装饰者模式,我们可以给具体组件添加额外的装饰来扩展其功能。

在 Main 类中,我们创建了一个 Espresso 的实例,并使用 Milk 和 Mocha 装饰它,最后输出了装饰后的描述和总价格。

以上内容基于GPT创建和整理。

关于作者

来自一线全栈程序员nine的探索与实践,持续迭代中。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 说明
  • 应用场景
  • 编程示例
  • 关于作者
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com