美文网首页
java 装饰者模式

java 装饰者模式

作者: 饱饱想要的灵感 | 来源:发表于2023-05-11 10:00 被阅读0次

装饰者模式是一种结构型设计模式,它允许你在运行时动态地修改对象的行为。在这种模式中,你可以通过将对象包装在一个装饰器对象中来添加新的行为,而不是修改原始对象的代码。

一、实现思路

在Java中,装饰者模式可以通过继承和组合来实现。通过创建一个包装器对象来实现的,该对象包装了原始对象,并在其上添加了新的行为或功能。步骤如下:

  1. 定义一个抽象组件(Component)类,它是被装饰者和装饰者的公共接口,可以是一个抽象类或接口。
  2. 定义一个具体组件(ConcreteComponent)类,它是抽象组件的实现类。
  3. 定义一个抽象装饰者(Decorator)类,它也是抽象组件的子类,它包含一个抽象组件类型的成员变量,以及一个构造方法,用于初始化该成员变量。
  4. 定义一个具体装饰者(ConcreteDecorator)类,它是抽象装饰者的实现类,它重写了抽象装饰者的方法,并在其中调用了被装饰者的方法,同时还可以添加自己的行为。

二、简单示例

下面是一个简单的示例,演示如何使用装饰者模式来动态地添加新的行为。

首先,我们定义一个接口Component,它是所有组件的基类:

public interface Component {
    void operation();
}

然后,我们定义一个具体的组件ConcreteComponent,它实现了Component接口:

public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent operation");
    }
}

现在,我们可以定义一个装饰器Decorator,它也实现了Component接口,并且包含一个Component类型的成员变量,用于存储被装饰的对象:

public abstract class Decorator implements Component {
    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        component.operation();
    }
}

注意,Decorator是一个抽象类,它的operation()方法调用了被装饰对象的operation()方法。

接着,我们可以定义具体的装饰器ConcreteDecorator,它继承自Decorator,并且可以添加新的行为:

public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        System.out.println("ConcreteDecorator operation");
    }
}

最后,我们可以使用装饰器模式来创建一个具有新行为的对象:

Component component = new ConcreteComponent();
component.operation(); // 输出 "ConcreteComponent operation"

Component decoratedComponent = new ConcreteDecorator(component);
decoratedComponent.operation(); // 输出 "ConcreteComponent operation" 和 "ConcreteDecorator operation"

在这个示例中,我们首先创建了一个ConcreteComponent对象,然后使用ConcreteDecorator来装饰它,从而添加了新的行为。当我们调用decoratedComponent的operation()方法时,它会先调用被装饰对象的operation()方法,然后再添加新的行为。

三、咖啡例子

一个经典的例子是咖啡店的咖啡。咖啡店通常会提供多种咖啡,例如浓缩咖啡、拿铁咖啡、卡布奇诺等。每种咖啡都有其基本配方,但客户可以根据自己的口味添加额外的配料,例如牛奶、糖浆、奶泡等。

在这种情况下,咖啡可以看作是一个基本对象,而添加的配料可以看作是装饰器。客户可以根据自己的喜好选择不同的装饰器来定制自己的咖啡。

下面是一个简单的Java代码示例,演示如何使用装饰者模式来制作咖啡。

首先,我们定义一个基本的咖啡接口,它包含了获取咖啡名称和价格的方法:

public interface Coffee {
    String getName();
    double getPrice();
}

然后,我们实现一个基本的浓缩咖啡类,它实现了Coffee接口:

public class Espresso implements Coffee {
    @Override
    public String getName() {
        return "Espresso";
    }

    @Override
    public double getPrice() {
        return 1.99;
    }
}

接下来,我们定义一个装饰器接口,它也实现了Coffee接口,但是它还包含了一个setCoffee方法,用于设置要装饰的咖啡对象:

public interface CoffeeDecorator extends Coffee {
    void setCoffee(Coffee coffee);
}

再然后,我们实现一个牛奶装饰器,它将牛奶添加到咖啡中:

public class MilkDecorator implements CoffeeDecorator {
    private Coffee coffee;

    @Override
    public void setCoffee(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public String getName() {
        return coffee.getName() + ", Milk";
    }

    @Override
    public double getPrice() {
        return coffee.getPrice() + 0.5;
    }
}

最后,我们可以使用这些类来制作不同的咖啡:

public class CoffeeShop {
    public static void main(String[] args) {
        // 制作一杯浓缩咖啡
        Coffee espresso = new Espresso();
        System.out.println(espresso.getName() + ": $" + espresso.getPrice());

        // 制作一杯加牛奶的浓缩咖啡
        Coffee milkEspresso = new MilkDecorator();
        milkEspresso.setCoffee(new Espresso());
        System.out.println(milkEspresso.getName() + ": $" + milkEspresso.getPrice());

        // 制作一杯加牛奶和糖浆的浓缩咖啡
        Coffee syrupMilkEspresso = new SyrupDecorator();
        syrupMilkEspresso.setCoffee(new MilkDecorator());
        syrupMilkEspresso.getCoffee().setCoffee(new Espresso());
        System.out.println(syrupMilkEspresso.getName() + ": $" + syrupMilkEspresso.getPrice());
    }
}

输出结果如下:

复制代码Espresso: $1.99
Espresso, Milk: $2.49
Espresso, Milk, Syrup: $3.49

这个例子展示了如何使用装饰者模式来动态地添加行为或功能。客户可以根据自己的喜好选择不同的装饰器来定制自己的咖啡,而不需要修改基本的咖啡类。

四、jdk中的应用

Java的IO库中,InputStream和OutputStream是抽象类,它们的子类实现了不同的输入输出方式,如FileInputStream和FileOutputStream、ByteArrayInputStream和ByteArrayOutputStream等。这些子类都是装饰者模式的具体实现。

下面是一个简单的例子,演示了如何使用装饰者模式来实现文件读写操作:

// 创建一个文件输入流
InputStream inputStream = new FileInputStream("test.txt");

// 使用BufferedInputStream装饰文件输入流,添加缓冲功能
InputStream bufferedInputStream = new BufferedInputStream(inputStream);

// 使用DataInputStream装饰BufferedInputStream,添加读取基本数据类型的功能
DataInputStream dataInputStream = new DataInputStream(bufferedInputStream);

// 读取文件中的数据
int num = dataInputStream.readInt();
String str = dataInputStream.readUTF();

// 关闭流
dataInputStream.close();

在这个例子中,我们首先创建了一个文件输入流,然后使用BufferedInputStream装饰它,添加了缓冲功能。接着,我们又使用DataInputStream装饰BufferedInputStream,添加了读取基本数据类型的功能。最后,我们通过DataInputStream读取了文件中的数据,并关闭了流。

这个例子中,我们使用了两个装饰者类来装饰文件输入流,它们分别是BufferedInputStream和DataInputStream。这两个类都是InputStream的子类,同时也是装饰者类。它们的作用是在文件输入流的基础上添加额外的功能,例如缓冲、读取基本数据类型等。

相关文章

  • java IO 的知识总结

    装饰者模式 因为java的IO是基于装饰者模式设计的,所以要了解掌握IO 必须要先清楚什么事装饰者模式(装饰者模式...

  • 设计模式 | 装饰者模式及典型应用

    前言 本文的主要内容: 介绍装饰者模式 示例 源码分析装饰者模式的典型应用Java I/O 中的装饰者模式spri...

  • 再谈装饰者模式(总结)

    在之前的文章 浅谈装饰者模式+JAVA I/O中的装饰者模式 中,浅谈了一下装饰者模式,这篇文章来总结一下装饰者模...

  • Android里一个装饰者模式的应用场景——给RecyclerV

    Java中最常见的装饰者模式应用就是IO流的设计了。先简单回顾一下装饰者模式: 装饰者模式的思想就是在被包装者原有...

  • 装饰者模式——IO流运用

    推荐博客Java设计模式学习09Java设计模式学习09Java设计模式学习09 装饰者模式还是比较难懂的。。。。...

  • Java设计模式之 —— 装饰者(Decorator) — 点

    Java设计模式之 —— 装饰者(Decorator) — 点炒饭 下面会用做炒饭的例子来描述一下装饰者设计模式,...

  • java中的代理模式与装饰者模式的区别

    java中的代理模式与装饰者模式的区别 代理模式与装饰者模式看起来很像,都实现基础对象实现的接口,在其自身对象中都...

  • java - 装饰者模式

    装饰者模式 装饰者模式:动态将责任添加到对象上。如果需要扩展功能,装饰者提供了比继承更有弹性的解决方案。装饰者模式...

  • Java装饰者模式

    1、装饰者模式的定义 装饰者模式是在已有功能的基础之上,动态地添加更多功能的一种方式,这些新加的代码装饰了原有类的...

  • java装饰者模式

    java中增强方法的功能有三种方式 1.通过继承,重写父类的方法,在调用super的基础上,再添加代码 2.动态代...

网友评论

      本文标题:java 装饰者模式

      本文链接:https://www.haomeiwen.com/subject/orlssdtx.html