既存のクラスに新たに機能を追加するために
Decoratorクラスでラップして機能を追加する構造になります。
ラップ方法は、継承を使わずにプログラムの実行時に機能を追加します。
(動的にオブジェクトに機能を追加できる構造)
Decoratorパターン クラス図 |
ConcreteComponent・・・Conponentクラスの機能を実装した具象クラス。
Decorator・・・・・・・・・・・メンバー変数にComponentを持つ抽象クラス。
(※operationメソッドで、Componentのoperationを呼ぶ。)
CooncreteDecorator・・・飾りつけをした具象クラス。
--------------------------------------------------
Componentにあたるクラス。
ファイル名:Display.java
public abstract class Display {
public abstract int getColumns(); // 横の文字数を得る
public abstract int getRows(); // 縦の行数を得る
public abstract String getRowText(int row); // row番目の文字列を得る
public void show() { // 全部表示するoperationメソッド
for (int i = 0; i < getRows(); i++) {
System.out.println(getRowText(i));
}
}
}
--------------------------------------------------
ConcreteComponentにあたるクラス。
ファイル名:StringDisplay.java
public class StringDisplay extends Display {
private String string; // 表示文字列
public StringDisplay(String string) { // 引数で表示文字列を指定
this.string = string;
}
// 独自のメソッド
public int getColumns() { // 文字数
return string.getBytes().length;
}
// 既存の機能
public int getRows() { // 行数は1
return 1;
}
public String getRowText(int row) { // rowが0のときのみ返す
if (row == 0) {
return string;
} else {
return null;
}
}
}
--------------------------------------------------
Decoratorにあたるクラス。
ファイル名:Border.java
public abstract class Border extends Display {
protected Display display; // この飾り枠がくるんでいる「中身」を指す
protected Border(Display display) { // インスタンス生成時に「中身」を引数で指定
this.display = display;
}
}
--------------------------------------------------
ConcreteDecoratorにあたるクラス①。
ファイル名:SideBorder.java
public class SideBorder extends Border {
private char borderChar; // 飾りとなる文字
public SideBorder(Display display, char ch) { // コンストラクタでDisplayと飾り文字を指定
super(display);
this.borderChar = ch;
}
public int getColumns() { // 文字数は中身の両側に飾り文字分を加えたもの
return 1 + display.getColumns() + 1;
}
public int getRows() { // 行数は中身の行数に同じ
return display.getRows();
}
public String getRowText(int row) {
// 指定行の内容は、中身の指定行の両側に飾り文字をつけたもの
return borderChar + display.getRowText(row) + borderChar;
}
}
--------------------------------------------------
ConcreteDecoratorにあたるクラス②。
ファイル名:FullBorder.java
public class FullBorder extends Border {
public FullBorder(Display display) {
super(display);
}
public int getColumns() { // 文字数は中身の両側に左右の飾り文字分を加えたもの
return 1 + display.getColumns() + 1;
}
public int getRows() { // 行数は中身の行数に上下の飾り文字分を加えたもの
return 1 + display.getRows() + 1;
}
public String getRowText(int row) { // 指定した行の内容
if (row == 0) { // 上端の枠
return "+" + makeLine('-', display.getColumns()) + "+";
} else if (row == display.getRows() + 1) { // 下端の枠
return "+" + makeLine('-', display.getColumns()) + "+";
} else { // それ以外
return "|" + display.getRowText(row - 1) + "|";
}
}
private String makeLine(char ch, int count) { // 文字chをcount個連続させた文字列を作る
StringBuffer buf = new StringBuffer();
for (int i = 0; i < count; i++) {
buf.append(ch);
}
return buf.toString();
}
}
--------------------------------------------------
Mainクラス。
ファイル名:Main.java
public class Main {
public static void main(String[] args) {
// ConcreteComponentクラスのインスタンス
Display b1 = new StringDisplay("Hello, world.");
b1.show();
// ↓普通の結果
// Hello, world.
// ConcreteDecoratorクラスのインスタンスでデコレート
Display b2 = new SideBorder(b1, '#');
// ↑#でデコレート
b2.show();
// ↓デコレートした結果
// |#Hello, world.#|
// ConcreteDecoratorクラスのインスタンスでデコレート
Display b3 = new FullBorder(b2);
b3.show();
// ↓デコレートした結果
// +---------------+
// |#Hello, world.#|
// +---------------+
// もっともっと包む
Display b4 =
new SideBorder(
new FullBorder(
new FullBorder(
new SideBorder(
new FullBorder(
new StringDisplay("こんにちは。")
),
'*'
)
)
),
'/'
);
b4.show();
// 結果は三重の枠と*と/で飾られた「こんにちは。」が出力される。
}
}
0 件のコメント:
コメントを投稿