デザインパターン勉強会　第三回：Template Methodパターン


# はじめに
本エントリーは某社内で実施するデザインパターン勉強会向けの資料となります。
 本エントリーで書籍「[Java言語で学ぶデザインパターン入門](http://www.hyuki.com/dp/ "Java言語で学ぶデザインパターン入門")」をベースに学習を進めますが、サンプルコードはC#に置き換えて解説します。

第1回：[Iteratorパターン](http://qiita.com/Nuits/items/800f080d44b52e1cae18 "Iteratorパターン")
第2回：[Adapterパターン](http://qiita.com/Nanakusajp/items/747d1913b1e8bea8d340 "Adapterパターン")

---

# Templete Methodパターンとは
Templete Methodとは、スーパクラスで処理の大枠になるものを決め、サブクラスの中で具体的な内容を決めるデザインパターンです。  

---
# サンプルクラス図
![クラス図.PNG](https://qiita-image-store.s3.amazonaws.com/0/194515/5308edab-ddaa-77f6-ca73-3c19823a95f1.png)

---

# 各クラスの役割
| 名前　　　　|役割         |
|:-----------|:------------|
| AbstractDisplay       | メソッドDisplayのみ実装されている抽象クラス        |
| CharDisplay     | メソッドOpen,Print,Closeを実装しているクラス      |
| StringDisplay       | メソッドOpen,Print,Closeを実装しているクラス        |
| Main         | 動作テスト用のクラス          |

---

# AbstractDisplayクラス
AbstractDisplayクラスでは、Open,Print,Closeの抽象メソッドとDisplayが実装されている。  

* Displayメソッドでは、Printメソッドを5回呼び出す処理が書かれている  
  
```
    public abstract class AbstractDisplay
    {
        public abstract void Open();
        public abstract void Print();
        public abstract void Close();

        public void Display()
        {
            Open();
            for(int i = 0; i < 5; i++)
            {
                Print();
            }
            Close();
        }
    }
```

---

# CharDisplayクラス
CharDisplayクラスはサブクラスであり、以下のメソッドが実装されている。

* メソッドの処理  

| メソッド名　　　　|処理         |
|:-----------|:------------|
| Open       | 文字列"<<"を表示する       |
| Print     | コンストラクタで与えられた1文字を表示する      |
| Close       | 文字列">>"を表示する        |
  
    public class CharDisplay : AbstractDisplay
    {
        private char ch { get; set; }

        public CharDisplay(char ch)
        {
            this.ch = ch;
        }

        public override void Open()
        {
            Console.Write("<<");
        }

        public override void Print()
        {
            Console.Write(ch);
        }

        public override void Close()
        {
            Console.WriteLine(">>");
        }
    }

---

# StringDisplayクラス
CharDisplayクラスと同様にこちらのクラスもサブクラスとなっている。
以下のメソッドを実装している。

* メソッドの処理    

| メソッド名　　　　|処理         |
|:-----------|:------------|
| Open       | 文字列"+------+"を表示する       |
| Print     | コンストラクタで与えられていた文字列を""と""で挟んでを表示する      |
| Close       | 文字列"+------+"を表示する        |  



    public class StringDisplay : AbstractDisplay
    {
        private string stringView { set; get; }
        private int width { set; get; }

        public StringDisplay(string stringView)
        {
            this.stringView = stringView;
            int stringViewLength = System.Text.Encoding.GetEncoding(932).GetByteCount(stringView);
            this.width = stringViewLength;
        }

        public override void Open()
        {
            PrintLine();
        }

        public override void Print()
        {
            Console.WriteLine("|" + stringView + "|");
        }

        public override void Close()
        {
            PrintLine();
        }

        private void PrintLine()
        {
            Console.Write("+");
            for(int i = 0; i < width; i++)
            {
                Console.Write("+");
            }

            Console.WriteLine("+");
        }
    }

---

# Mainクラス
Mainクラスは動作テストを行うものになる。今まで作ったクラスのインスタンスを生成し、Displayメソッドを呼び出している。
今回はMainクラスという名前ではなく、Startというクラス名にして実装した。  


    class Start
    {
        static void Main(string[] args)
        {
            AbstractDisplay charDisplay = new CharDisplay('H');
            AbstractDisplay stringDisplayOnce = new StringDisplay("こんにちは");
            AbstractDisplay stringDisplayTwice = new StringDisplay("こんばんわ");

            charDisplay.display();
            stringDisplayOnce.display();
            stringDisplayTwice.display();

            Console.ReadLine();
        }
    }

Console.ReadLineを入れることにより、ボタンを押下するまでコンソールが表示できるように変更した。

---

# 実行結果
実行すると以下のようになる。

```
<<HHHHH>>
++++++++++++
|こんにちは|
|こんにちは|
|こんにちは|
|こんにちは|
|こんにちは|
++++++++++++
++++++++++++
|こんばんわ|
|こんばんわ|
|こんばんわ|
|こんばんわ|
|こんばんわ|
++++++++++++
```

---

# Template Methodのメリット
このデザインパターンを使用するメリットとしては、以下の点になります。

* スーパークラス側でアルゴリズムを記載しているためサブクラスでアルゴリズムを書く必要がない
* スーパークラスで間違いを見つけた場合、それを直せばほかの修正がいらない
* サブクラスをスーパークラスと同一視している

---
# サンプルコード

以下に公開しています。

https://github.com/yukyam/TempleteMethodMaster