使用Java实现装饰者模式
首先
我会总结我在阅读了介绍了GoF设计模式的《增补修订版 Java语言学习设计模式入门》一书后所学的内容。
装饰者模式
装饰者指的是
翻译为中文后是:“日语翻译为“装饰者”。Decorator模式指的是通过不断地对原对象进行装饰(装饰)来进行功能扩展的模式。通过应用这种模式,可以在不改动原始类的情况下,灵活地进行功能扩展。”
人物亮相
抽象类
-
- Component
-
- 装飾(拡張)される対象の元となる抽象クラスを表します。
-
- Decorator
- Componentクラスを継承する抽象クラスで、装飾を行う側のクラスの元となるクラスです。 特筆すべき点として、装飾する対象であるComponentクラスをフィールドに持っている点が挙げられます。
实现类
-
- ConcreteComponent
-
- Componentクラスの実装クラスです。Componentクラスの持つ抽象メソッドを全て実装します。
-
- ConcreteDecorator
- Decoratorクラスの実装クラスです。DecoratorクラスはComponentクラスを継承しているため、Componentクラスの持つ抽象メソッドを実装する必要があります。
具体的例子
抽象类
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言語で学ぶデザインパターン入門