ActionScript 3 (Flash/AIR): GoF デザインパターン – Templete Method

テンプレートメソッドパターンは、処理をサブクラスに任せるデザインパターンだそうです。条件分岐を行う処理がある場合、その条件分岐の処理部分をサブクラスで実装するといったような具合です。

イマイチ説明が難しいので具体的に示すと、下記のクラスがあり、処理 B のところを条件によって変えたいとして。

ActionScript: NotTemplate.as

package jp.feb19.gof.templatemethod
{
        public class NotTemplate
        {
                public function NotTemplate()
                {
                        
                }
                
                public function doSmothing():void
                {
//                      ... 処理 A ...
                        
//                      ... 処理 B ...
                        
//                      ... 処理 C ...
                }
        }
}

方法としては、「1. if を使って分岐するか」、「2. サブクラスを使ってポリモーフィズムにするか」が考えられます。

1 だと下記のような実装になりますが、条件が増えるごとに if/else/else if を追加していかなければならなくなります。

ActionScript: NotTemplate.as

package jp.feb19.gof.templatemethod
{
        public class NotTemplate
        {
                private var status:int;
                
                public function NotTemplate()
                {
                        
                }
                
                public function doSmothing():void
                {
//                      ... 処理 A ...
                        
                        if (status == 0)
//                              ... 処理B1 ...
                        else
//                              ... 処理B2 ...
                                
                        
//                      ... 処理 C ...
                }
        }
}

2 では処理 B のところを関数呼び出しにして、サブクラスに実装させるようにします。
サブクラス側から見れば、それ以外のところは共通処理になっているので、元のクラスはテンプレートと呼べます。

ActionScript: Template.as

package jp.feb19.gof.templatemethod
{
        public class Template
        {
                private var status:int;
                
                public function Template()
                {
                        
                }
                
                public function doSmothing():void
                {
//                      ... 処理 A ...
                        trace("start.");
                        
                        execute();
                        
//                      ... 処理 C ...
                        trace("stop.");
                }
                
                protected function execute():void
                {
                        trace("greeting");
                }
        }
}

ActionScript: ConcreteMorning.as

// サブクラス A
package jp.feb19.gof.templatemethod
{
        public class ConcreteMorning extends Template
        {
                public function ConcreteMorning()
                {
                        super();
                }
                
                override protected function execute():void
                {
                        trace("good morning.");
                        super.execute();
                }
        }
}

ActionScript: ConcreteEvening.as

// サブクラス B
package jp.feb19.gof.templatemethod
{
        public class ConcreteEvening extends Template
        {
                public function ConcreteEvening()
                {
                        super();
                }
                
                override protected function execute():void
                {
                        trace("good evening.");
                }
        }
}

ActionScript: TemplateMethodTest.as

// メインクラス
package jp.feb19.gof.templatemethod
{
        import flash.display.Sprite;
        
        public class TemplateMethodTest extends Sprite
        {
                public function TemplateMethodTest()
                {
                        super();
                        
                        var morning:Template = new ConcreteMorning();
                        morning.doSmothing();
                        
                        var evening:Template = new ConcreteEvening();
                        evening.doSmothing();
                }
        }
}

出力

start.
good morning.
greeting
stop.
start.
good evening.
stop.

設計段階でテンプレートクラスを組んでおいて、各処理毎に実装サブクラスを分けておき、実装が必要なメソッドは override していき、それらのクラスを使用します。親クラスで処理を共通化させます。

このテンプレートクラスは直接使用しないので、抽象クラス (Abstract Class) といい、それを継承した直接使用するサブクラスを具象クラス (Concrete Class) というそうです。

継承というテクニックを使い始めたらいつの間にか Template Method パターンを使っている、っていうことは多々あると思います。

自分は同じアニメーションで出現させるけど見た目がちょっと違う別のリンケージシンボルのクラスでよく使用しています。例えばダイアログを表示するときとか。

if/else if/else いくら増えようが別にかわらんくなーい?と思う方は別に気にする必要ないと思います。僕も必要以上にクラスを作るのはファイル増えて鬱陶しいと思うので。