未来の私へ送るデザインパターン 2/24 [iterator]
このシリーズは、この内容を忘れた未来のcacaponが読んだときに、
自力でそれを使ったプログラムが自作できることを目的として作られました~
こちらの記事は、以下を主に参考に作成しております♪
残りは、cacaponの記憶の片隅にある情報がソース元になります~
iteratorとは?
iteratorは日本語だと「反復子」というそうです…
あんまり聞いたことがないです~
プログラマだとイメージつきやすいのはfor文の i変数ですかね?
繰り返すときにどんどん増えてくアレです~
日常生活だと…分からないなぁ…
参考URLだと、最もイメージしやすいデザインパターンがこれらしいので、
こちらから紹介されていました~
メリットとしては、
配列の中から情報の一覧を取得したり、検索を掛けたりする際、
中の構造に関係なく情報を取得できるそうです~
凄いですね~
例題
フッキー博士は未知の生物の研究者。
ある特徴を持つ生物に対し、「パチモン」と名づけ、
パチモンの生態をまとめた図鑑を作ることにしました。
協力者にお願いしていたパチモンの情報が5つ届いたので、
図鑑に情報を追加することにします。
届いた情報は以下の通りです。
- 名前:マカフクサ 分類:しょくぶつパチモン
- 名前:ヒグアナ 分類:イグアナパチモン
- 名前:ヨロイガメ 分類:カメパチモン
- 名前:マメッポー 分類:ハトパチモン
- 名前:ネズット 分類:ネズミパチモン
図鑑に追加した後、
図鑑利用者が追加した情報の一覧を見れるようにしてください。
怒られないかなぁ…大丈夫かなぁ…
itaratorを使わないで作ったプログラム
こんな構成で作りました~
# main.py from user import User from doctorfukkey import DoctorFukkey DrFukkey = DoctorFukkey() you = User() DrFukkey.work() you.lookpicturebook()
# doctorfukkey.py from picturebook import PictureBook class DoctorFukkey(): def work(self): use = PictureBook() use.add_pachimon_info('マカフクサ', 'しょくぶつパチモン') use.add_pachimon_info('ヒグアナ', 'イグアナパチモン') use.add_pachimon_info('ヨロイガメ', 'カメパチモン') use.add_pachimon_info('マメッポー', 'ハトパチモン') use.add_pachimon_info('ネズット', 'ネズミパチモン')
# user.py from pprint import pprint from picturebook import PictureBook class User(): def lookpicturebook(self): use = PictureBook() pprint(use.show_pachimon_info())
# picturebook.py やむを得ずシングルトンを使用しています class PictureBook(): _instance = None _pachimon_info = {} def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) cls._pachimon_info = {} return cls._instance def add_pachimon_info(self, name, classifying): PictureBook._pachimon_info[name] = classifying def show_pachimon_info(self): return PictureBook._pachimon_info
その後…
考えられるのはこんなところでしょうか?
- 図鑑の登録形式が変わった。(Noの追加とか、体長、体重の追加など)
- 一覧でなくで特定の条件のものを表示したい
- キーワードから特定のパチモンを表示できる
…最初にDict型で作ってしまったせいか、あまりiteratorの恩恵がわかりにくいかもです…
itaratorを使って作ったプログラム
こんな感じにするそうです。
ではやってみましょう~
# main.py from concreteaggregate import ConcreteAggregate from concreteiterator import ConcreteIterator use = ConcreteAggregate() use.add_pachimon_info('マカフクサ', 'しょくぶつパチモン') use.add_pachimon_info('ヒグアナ', 'イグアナパチモン') use.add_pachimon_info('ヨロイガメ', 'カメパチモン') use.add_pachimon_info('マメッポー', 'ハトパチモン') use.add_pachimon_info('ネズット', 'ネズミパチモン') iterator = ConcreteIterator(use) while(iterator.hasnext()): print(iterator.next())
# iterator.py from abc import ABCMeta, abstractmethod class Iterator(metaclass=ABCMeta): @abstractmethod def hasnext(self): pass @abstractmethod def next(self): pass
# concreteiterator.py from iterator import Iterator class ConcreteIterator(Iterator): def __init__(self, concreteAggregate): self.__concreteaggregate = concreteAggregate self.__last = 0 def next(self): info = self.__concreteaggregate.get_pachimon_info(self.__last) self.__last += 1 return info def hasnext(self): if self.__last >= len(self.__concreteaggregate.show_pachimon_list()): return False return True
# aggregate.py from abc import ABCMeta, abstractmethod from iterator import Iterator class Aggregate(metaclass=ABCMeta): def __init__(self): self.Iterator = Iterator() @abstractmethod def iterator(self): pass
# concreteaggregate.py from aggregate import Aggregate from concreteiterator import ConcreteIterator class ConcreteAggregate(Aggregate): def __init__(self): self.__pachimon_info = [] def add_pachimon_info(self, name, classflying): self.__pachimon_info.append([name, classflying]) def get_pachimon_info(self, index): return self.__pachimon_info[index] def show_pachimon_list(self): return self.__pachimon_info def iterator(self): return ConcreteIterator(ConcreteAggregate())
その後...の対応例
今回は対応例が思いつかなかったので割愛します~