Decoratorパターン

###Derocatorパターンとは
オブジェクトに飾り付けをほどこしていく。

###Componentの役
機能を追加するときの核になる役。

````java
package decorator;

public abstract class Display {
	public abstract int getColumns();
	public abstract int getRows();
	public abstract String getRowText(int row);
	public final void show() {
		for (int i = 0; i < getRows(); i++) {
			System.out.println(getRowText(i));
		}
	}
}
````

###ConcreteComponentの役
Component役のインターフェースを実装する役。

````java
package decorator;

/**
 * 1行の文字列を表示するクラス
 */
public class StringDisplay extends Display{
	private String string;

	public StringDisplay(String string) {
		this.string = string;
	}

	@Override
	public int getColumns() {
		return string.getBytes().length;
	}

	@Override
	public int getRows() {
		return 1;
	}

	@Override
	public String getRowText(int row) {
		return row == 0 ? string : null;
	}
}
````

###Decorator(装飾者)の役
Component役と同じインターフェースを持つ。
また、Decorator役が飾る対象となるComponent役を持つ。
この役は自分が飾る対象を知っている。

````java
package decorator;

/**
 * 飾り枠を表すクラス
 */
public abstract class Border extends Display {
	// この飾り枠がくるんでいる「中身」をさす
	protected Display display;
	protected Border(Display display) {
		this.display = display;
	}
}
````

###ConcreteDecorator(具体的な装飾者)の役
具体的なDecoratorの役。

````java
package decorator;

/**
 * 文字列の左右に決まった文字で飾りをつけるクラス
 *
 */
public class SideBorder extends Border {
	private char borderChar;

	protected SideBorder(Display display, char ch) {
		super(display);
		this.borderChar = ch;
	}

	@Override
	public int getColumns() {
		// 文字数は両側に飾り文字分を加えたもの
		return 1 + display.getColumns() + 1;
	}

	@Override
	public int getRows() {
		return display.getRows();
	}

	@Override
	public String getRowText(int row) {
		return borderChar + display.getRowText(row) + borderChar;
	}
}
````

````java
package decorator;

/**
 * 上下左右に飾りをつけるクラス
 *
 */
public class FullBorder extends Border{

	protected FullBorder(Display display) {
		super(display);
	}

	@Override
	public int getColumns() {
		// 文字数は両側に飾り文字分を加えたもの
		return 1 + display.getColumns() + 1;
	}

	@Override
	public int getRows() {
		// 文字数は上下に飾り文字分を加えたもの
		return 1 + display.getRows() + 1;
	}

	@Override
	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) {
		StringBuffer buf = new StringBuffer();
		for (int i = 0; i < count; i++) {
			buf.append(ch);
		}
		return buf.toString();
	}
}
````

###呼び出し元

````java
package decorator;

public class Main {
	public static void main(String[] args) {
		Display d1 = new StringDisplay("Hello world");
		Display d2 = new SideBorder(d1, '#');
		Display d3 = new FullBorder(d2);
		d1.show();
		d2.show();
		d3.show();
	}
}
````

###実行結果

![スクリーンショット 2020-09-09 14.19.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197834/81e11759-99b6-4cca-8b38-fc00a9a7e6a4.png)

包めば包むほど機能が追加されていく。
その際、包まれる側を変更することなく、機能の追加を行うことができる。

https://github.com/aki0207/decorator

こちらを参考にさせていただきました。
<a href="https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030/ref=sr_1_1?ie=UTF8&qid=1454743284&sr=8-1&keywords=java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80">増補改訂版Java言語で学ぶデザインパターン入門</a>