概要
Template Methodは、スーパークラスにいくつかの抽象メソッドを用意して処理の枠組みを決め、サブクラスでそれらを実装して具体的な処理を決定するデザインパターン。
サンプルプログラム
結城浩先生の増補改訂版Java言語で学ぶデザインパターン入門のJavaプログラムをTypeScriptで写経した。
以下のようなスーパークラスAbstractDisplay
を用意する。
export abstract class AbstractDisplay {
public abstract open(): string;
public abstract print(): string;
public abstract close(): string;
public display(): string {
const open = this.open();
let print = '';
for (let i = 0; i < 5; i++) {
this.print();
print += this.print();
}
const close = this.close();
return open + print + close;
}
}
文字列を5回繰り返してカッコなどの装飾をつけて表示するためのスーパークラスである。どのような装飾をつけるかは、サブクラスの実装による。
サブクラスCharDisplay
を以下のように実装する。
import { AbstractDisplay } from 'templateMethod/abstractDisplay';
export class CharDisplay extends AbstractDisplay {
private ch: string;
public constructor(ch: string) {
super();
this.ch = ch;
}
public open(): string {
return '<<';
}
public print(): string {
return this.ch;
}
public close(): string {
return '>>';
}
}
以下のテストが通る。
test('charDisplay', () => {
const charDisplay: AbstractDisplay = new CharDisplay('H');
const actual = charDisplay.display();
const expected = '<<HHHHH>>';
expect(actual).toEqual(expected);
});
サブクラスStringDisplay
を以下のように実装する。
import { AbstractDisplay } from 'templateMethod/abstractDisplay';
export class StringDisplay extends AbstractDisplay {
private string: string;
private width: number;
constructor(string: string) {
super();
this.string = string;
this.width = string.length;
}
public open(): string {
return this.printLine();
}
public print(): string {
return '|' + this.string + '|\n';
}
public close(): string {
return this.printLine();
}
private printLine(): string {
let line = '';
for (let i = 0; i < this.width; i++) {
line += '-';
}
return '+' + line + '+\n';
}
}
以下のテストが通る。
test('stringDisplay', () => {
const stringDisplay: AbstractDisplay = new StringDisplay('Hello, World');
const actual = stringDisplay.display();
const expected = `+------------+
|Hello, World|
|Hello, World|
|Hello, World|
|Hello, World|
|Hello, World|
+------------+
`;
expect(actual).toEqual(expected);
});
考察・感想
本のJavaプログラムだと、AbstractDisplay
のdisplay
メソッドはfinal
がついていてオーバーライド禁止になっていたが、typescriptでそれを表現する方法がわからなかった。この記事ではReadOnly<T>
型のインスタンスを返すファクトリメソッドを用意する方法でメソッドをオーバーライド禁止にしている。ちょうど次回はファクトリメソッド。