使用Java实现装饰者模式

首先

我会总结我在阅读了介绍了GoF设计模式的《增补修订版 Java语言学习设计模式入门》一书后所学的内容。

装饰者模式

装饰者指的是

翻译为中文后是:“日语翻译为“装饰者”。Decorator模式指的是通过不断地对原对象进行装饰(装饰)来进行功能扩展的模式。通过应用这种模式,可以在不改动原始类的情况下,灵活地进行功能扩展。”

人物亮相

image.png

抽象类

    • Component

 

    • 装飾(拡張)される対象の元となる抽象クラスを表します。

 

    • Decorator

 

    Componentクラスを継承する抽象クラスで、装飾を行う側のクラスの元となるクラスです。 特筆すべき点として、装飾する対象であるComponentクラスをフィールドに持っている点が挙げられます。

实现类

    • ConcreteComponent

 

    • Componentクラスの実装クラスです。Componentクラスの持つ抽象メソッドを全て実装します。

 

    • ConcreteDecorator

 

    Decoratorクラスの実装クラスです。DecoratorクラスはComponentクラスを継承しているため、Componentクラスの持つ抽象メソッドを実装する必要があります。

具体的例子

image.png

抽象类

SpongeCakeクラス

public abstract class SpongeCake {
    public abstract String getName(); // 名前を得る

    public abstract int getPrice(); // 価格を得る

    public void show() { // 名前と価格を表示する
        System.out.println(getName() + ":" + getPrice() + "円");
    }
}

在SpongeCake类中,我们定义了一个抽象方法来获取名称和价格,并定义了一个具体方法来显示它们。
这只是一个普通的无装饰的海绵蛋糕形象。
关于抽象类的实际处理将在下述的子类中实现。
没有特别困难的地方。

Decoratorクラス

public abstract class Decorator extends SpongeCake {
    protected SpongeCake spongeCake; // この飾り枠がくるんでいる「中身」を指す

    protected Decorator(SpongeCake spongeCake) { // インスタンス生成時に「中身」を引数で指定
        this.spongeCake = spongeCake;
    }
}

装饰者类继承自上述的海绵蛋糕类,但没有重写抽象方法,因此它是一个抽象类。
值得注意的是,装饰者类具有一个指向海绵蛋糕对象的字段,并在构造函数中将对象的生成参数指定为参数。

实现类

    ShortCakeクラス
public class ShortCake extends SpongeCake {

    @Override
    public String getName() { // 親クラスの名前を得るメソッドをオーバーライド
        return "ショートケーキ";
    }

    @Override
    public int getPrice() { // 親クラスの価格を得るメソッドをオーバーライド
        return 500;
    }

}
    ChocolateCakeクラス
public class ChocolateCake extends SpongeCake {

    @Override
    public String getName() { // 親クラスの名前を得るメソッドをオーバーライド
        return "チョコレートケーキ";
    }

    @Override
    public int getPrice() { // 親クラスの価格を得るメソッドをオーバーライド
        return 700;
    }

}

ShortCake类和ChocolateCake类是SpongeCake类的实现类。它们在仅有海绵蛋糕的基础上做了一些装饰,使得蛋糕更加具体。它们重写了抽象方法getName()和getPrice(),分别返回名称和价格。在这里没有特别困难的地方。

StrawberryDecoratorクラス

public class StrawberryDecorator extends Decorator {

    public StrawberryDecorator(SpongeCake spongeCake) { // コンストラクタで飾り付けの対象を渡す
        super(spongeCake);
    }

    @Override
    public String getName() { // 中身の名前の先頭にイチゴを加えたもの
        return "イチゴ" + spongeCake.getName();
    }

    @Override
    public int getPrice() { // 中身の価格に100を加えたもの
        return spongeCake.getPrice() + 100;
    }

}

BananaDecoratorクラス

public class BananaDecorator extends Decorator {

    public BananaDecorator(SpongeCake spongeCake) { // コンストラクタで飾り付けの対象を渡す
        super(spongeCake);
    }

    @Override
    public String getName() { // 中身の名前の先頭にバナナを加えたもの
        return "バナナ" + spongeCake.getName();
    }

    @Override
    public int getPrice() { // 中身の価格に300を加えたもの
        return spongeCake.getPrice() + 300;
    }

}

StrawberryDecorator类和BananaDecorator类是Decorator类的实现类。
它们都会在构造函数中将指定的海绵蛋糕(或其子类)添加草莓和香蕉作为装饰。
同时,它们也会相应地增加价格。

重点是构造函数的参数为SpongeCake类型。
从这一点可以看出,可以将SpongeCake类,或者其子类ShortCake类、ChocolateCake类作为构造函数的参数。
另外,不可忽视的是Decorator类也是SpongeCake类的子类。
换句话说,装饰用的StrawberryDecorator类的构造函数参数可以指定继承了Decorator类的StrawberryDecorator类、BananaDecorator类。
这样一来,可以对装饰对象进行进一步的装饰。

执行类

    Mainクラス
public class Main {
    public static void main(String[] args) {
        // ショートケーキの生成
        SpongeCake s1 = new ShortCake();
        SpongeCake s2 = new StrawberryDecorator(s1);
        SpongeCake s3 = new BananaDecorator(s1);
        SpongeCake s4 = new StrawberryDecorator(new ShortCake());
        SpongeCake s5 = new StrawberryDecorator(new BananaDecorator(new ShortCake()));
        s1.show();
        s2.show();
        s3.show();
        s4.show();
        s5.show();
        System.out.println("--------------------------------------------");
        // チョコレートケーキの生成
        SpongeCake c1 = new ChocolateCake();
        SpongeCake c2 = new StrawberryDecorator(c1);
        SpongeCake c3 = new BananaDecorator(c1);
        SpongeCake c4 = new StrawberryDecorator(new ChocolateCake());
        SpongeCake c5 = new StrawberryDecorator(new BananaDecorator(new ChocolateCake()));
        c1.show();
        c2.show();
        c3.show();
        c4.show();
        c5.show();
    }
}

生成了ShortCake类和ChocolateCake类的实例,并对它们进行了装饰。
重点在于如同在StrawberryDecorator类和BananaDecorator类的说明中所述,由于装饰目标是作为构造函数参数指定的类,因此可以进行多种装饰。

另外,

SpongeCake s1 = new ShortCake();
SpongeCake s2 = new StrawberryDecorator(s1);

In Chinese, the phrase “と” can be translated as “和” (hé).

SpongeCake s4 = new StrawberryDecorator(new ShortCake());

只是用于装饰的,将ShortCake作为构造函数的参数进行指定,虽然写法有所不同,但实际上是相同的处理。

执行结果

运行Main.java的结果如下所示。
可以确认原始的ShortCake和ChocolateCake正在逐渐被装饰。

ショートケーキ:500円
イチゴショートケーキ:600円
バナナショートケーキ:800円
イチゴショートケーキ:600円
イチゴバナナショートケーキ:900円
--------------------------------------------
チョコレートケーキ:700円
イチゴチョコレートケーキ:800円
バナナチョコレートケーキ:1000円
イチゴチョコレートケーキ:800円
イチゴバナナチョコレートケーキ:1100円

优点

Decorator模式的好处如下:
1. 可以在不更改父类的情况下添加功能。
2. 可以通过组合所需的组件来添加多样的功能。

总结

我学习了关于Decorator模式,它是将装饰逐步应用于对象的模式。
如果您感兴趣的话,以下是我上传的示例代码,请参考。

    Decoratorサンプルコード

此外,其他设计模式的综合总结可以在下方找到,也可供参考。

    [随時更新]Javaでデザインパターンまとめ

文献引用

    増補改訂版 Java言語で学ぶデザインパターン入門
广告
将在 10 秒后关闭
bannerAds