デザインパターン Template Method

TemplateMethod パターンを書いてみる。例のごとく結城さんの本を参考にJavaのコードを書きます。


増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

public abstract class AbstractDisplay{

  public abstract void open();
  public abstract void print();
  public abstract void close();

  public final void display(){
	open();
	for(int i = 0; i<5 ; i++){
	    print();
	}
	close();
  }
}

スーパークラス(抽象クラス)を用意します。display()がテンプレートメソッドです。open,print,closeといった抽象メソッドをどのように使い回すのか、という処理の枠組みを作ります。テンプレートメソッドはfinalをつけて、オーバーライドされないようにしておきます。抽象メソッドはサブクラスで実装します。

public class StringDisplay extends AbstractDisplay{

    private String string;
    private int width;
    public StringDisplay(String string){
    	this.string = string;
	this.width  = string.getBytes().length;
    }
    
    public void open(){
    	printLine();
    }
    
    public void print(){
    	System.out.println("|" +string +"|");
    }
    
    public void close(){
    	printLine();
    }
    
    public void printLine(){
        System.out.print("+");
	
	for(int i =0 ; i 

本を参考に(そのままに・・・)コンストラクタに渡した文字を修飾する というサブクラスを実装します。

public class Main{
	public static void main(String[] args){
		AbstractDisplay d1 = new StringDisplay("こんちわ!");
		d1.display();
	}
}

クライアントコードは上記のようになりました。

                      • +
こんちわ!
こんちわ!
こんちわ!
こんちわ!
こんちわ!
                      • +

出力はこんな感じになります。



PerlだとTemplateMethodパターンはどんな風になるんでしょかね。そもそもPerlでは抽象クラスをつかってほげほげってやり方はあまり一般的でないような希ガス。とにかく、直訳的にJavaからPerlへとコードを書き換えてみます。

package AbstractDisplay;

use strict;

sub new{
  my $class = shift;
  bless {} => $class;
}

sub open{ die }
sub print{ die }
sub close{ die }

sub display{ 
  my $self = shift;
  $self->open();
  for(1..5){ $self->print() };
  $self->close();
}

1;

テンプレートメソッドを持った抽象クラスを作りました。抽象メソッドはオーバーライドされないとdieするという形で再現します。Javaであればテンプレートメソッドはfinalで保護するのですが、Perlの場合 どういった方法でそれを再現すればいいのかよくわかりません(そこまで気にしなくていいのかも)

package StringDisplay;

use strict;
use base qw(AbstractDisplay);

sub new{
  my $class = shift;
  bless { string => shift} , $class;
}

sub open{
  my $self = shift;
  $self->printLine();
}

sub print{
  my $self = shift;
  printf "|%s|?n" , $self->{string};
}

sub close{
  my $self = shift;
  $self->printLine();
}

sub printLine{
  my $self = shift;
  print "+";
  for(1..length $self->{string}){
    print "-";
  }
  print "+?n";
}

1;

サブクラスの実装は上記のようになります。抽象クラスの抽象メソッドをオーバーライドしています。

use strict;
use StringDisplay;

my $d1 = StringDisplay->new("失礼します");
$d1->display();

exit;

クライアントコードは上記のようになります。コンストラクタに渡された文字列が修飾されて出力されます。

                          • +
失礼します!
失礼します!
失礼します!
失礼します!
失礼します!
                          • +

礼儀正しい人が出来ました。

Template Methodパターンはいろいろなデザインパターンに応用されているので忘れないようにします。