🐈

Template Methodパターンを学ぶ【Python】

2022/02/06に公開

一言で言うと

ひな形。抽象クラスでは動作の概要と処理の流れを、具象クラスはで詳細を実装する。

コードサンプル

ディレクトリ構造
template_method
├── abstract_display.py
├── char_display.py
├── main.py
└── string_display.py
main.py
from abstract_display import AbstractDisplay
from char_display import CharDisplay
from string_display import StringDisplay


def main() -> None:
    d1: AbstractDisplay = CharDisplay('H')
    d2: AbstractDisplay = StringDisplay('Hello, world!')
    d3: AbstractDisplay = StringDisplay('こんにちは.')

    d1.display()
    d2.display()
    d3.display()


if __name__ == '__main__':
    main()
abstract_display.py
from abc import ABCMeta, abstractmethod
from typing import final


class AbstractDisplay(metaclass=ABCMeta):
    @abstractmethod
    def open(self) -> None:
        pass

    @abstractmethod
    def print(self) -> None:
        pass

    @abstractmethod
    def close(self) -> None:
        pass

    @final
    def display(self) -> None:
        self.open()
        for _ in range(5):
            self.print()
        self.close()
char_display.py
from abstract_display import AbstractDisplay


class CharDisplay(AbstractDisplay):
    def __init__(self, ch: str) -> None:
        self.ch: str = ch

    def open(self) -> None:
        print('<<', end='')

    def print(self) -> None:
        print(self.ch, end='')

    def close(self) -> None:
        print('>>')
string_display.py
from abstract_display import AbstractDisplay
from unicodedata import east_asian_width
from functools import reduce
from operator import add


class StringDisplay(AbstractDisplay):
    def __init__(self, string: str) -> None:
        self.string: str = string
        #self.width: int = self.__str_len(string)
        self.width: int = reduce(
            # 全角2文字、半角1文字とする
            add, [2 if east_asian_width(ch) in 'FWA' else 1 for ch in string]
        )

    def open(self) -> None:
        self.__printLine()

    def print(self) -> None:
        print(f'|{self.string}|')

    def close(self) -> None:
        self.__printLine()

    def __printLine(self) -> None:
        print('+', end='')
        for _ in range(self.width):
            print('-', end='')
        print('+')

参考文献

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

Discussion