
こんにちは。虎の穴ラボのサカガミです。
今回はソフトウェア開発におけるデザインパターンについて 学習した内容を書かせていただきます。
デザインパターンとは?
デザインパターンとは、ソフトウェア設計における 一般的な問題を解決するための再利用可能な解決策のことです。 特定の問題に対する最適なアプローチを提供するテンプレートのようなもので、 共通の設計課題を解決するためのベストプラクティスがまとめられています。 経験豊富な開発者たちが直面した問題とその解決策が体系化されており、 コードの品質向上や保守性の向上に寄与します。
デザインパターンの利点
デザインパターンを使うことで、以下のような利点があります:
- コードの再利用性: 汎用的な解決策を提供するため、同じ問題に対して使い回すことができ、コードの一貫性が保たれる
- 可読性と理解の向上: よく知られたパターンを使うことで、他の開発者がコードを理解しやすくなる
- 保守性の向上: パターンに従った設計は、変更や拡張がしやすくなり、バグの発生を減少させる
- 効率的な開発: 問題解決のための時間を節約できる
デザインパターンの紹介
デザインパターンは20以上あるため、 今回は私が開発に取り入れやすそうだと思ったものを 3つピックアップして紹介します。
Observer パターン
Observer パターンは、オブジェクトの状態変化を他のオブジェクトに通知するパターンです。 例えば、GUI アプリケーションでボタンのクリックを他の部分に通知する場合に利用できます。
Python での実装例
from abc import ABC, abstractmethod class Subject: def __init__(self): self._observers = [] def attach(self, observer): self._observers.append(observer) def detach(self, observer): self._observers.remove(observer) def notify(self): for observer in self._observers: observer.update() class Observer(ABC): @abstractmethod def update(self): pass # 具体的なオブザーバークラス class ConcreteObserverA(Observer): def update(self): print("Observer A notified") class ConcreteObserverB(Observer): def update(self): print("Observer B notified") # 使用例 subject = Subject() observer_a = ConcreteObserverA() observer_b = ConcreteObserverB() subject.attach(observer_a) subject.attach(observer_b) subject.notify() # 出力: # Observer A notified # Observer B notified
実装内容の解説
- Subject クラス:
観察対象となるオブジェクト。
attachメソッドで Observer を追加し、detachメソッドで削除、notifyメソッドで Observer に通知を送ります。 - Observer クラス:
観察者の抽象クラス。
updateメソッドが抽象メソッドとして定義されています。 - ConcreteObserverA, ConcreteObserverB クラス:
Observer を実装した具体的なクラス。
updateメソッドで通知を受け取ります。
Memento パターン
Memento パターンは、オブジェクトの状態を保存し、後でその状態に戻すことができるようにするパターンです。 例えば、テキストエディタの「元に戻す」機能などで利用できます。
Python での実装例
class Memento: def __init__(self, state): self._state = state def get_state(self): return self._state class Originator: def __init__(self, state): self._state = state def get_state(self): return self._state def set_state(self, state): self._state = state def save_to_memento(self): return Memento(self._state) def restore_from_memento(self, memento): self._state = memento.get_state() # 使用例 originator = Originator("State1") print(f"Initial State: {originator.get_state()}") # 出力: # Initial State: State1 # 状態を保存 memento = originator.save_to_memento() # 状態を変更 originator.set_state("State2") print(f"State changed to: {originator.get_state()}") # 出力: # State changed to: State2 # 状態を復元 originator.restore_from_memento(memento) print(f"State restored to: {originator.get_state()}") # 出力: # State restored to: State1
実装内容の解説
- Memento クラス:
保存する状態を保持するクラス。
get_stateメソッドで状態を取得します。 - Originator クラス:
元のオブジェクト。
save_to_mementoメソッドで状態を保存し、restore_from_mementoメソッドで状態を復元します。
Strategy パターン
Strategy パターンは、アルゴリズムをクラスとしてカプセル化し、 それらを使い分けることで、動的にアルゴリズムを変更できるようにするパターンです。 例えば、異なる計算方法を動的に切り替える場合などに利用できます。
Python での実装例
from abc import ABC, abstractmethod class Strategy(ABC): @abstractmethod def execute(self, data): pass class ConcreteStrategyA(Strategy): def execute(self, data): return sorted(data) class ConcreteStrategyB(Strategy): def execute(self, data): return sorted(data, reverse=True) class Context: def __init__(self, strategy: Strategy): self._strategy = strategy def set_strategy(self, strategy: Strategy): self._strategy = strategy def execute_strategy(self, data): return self._strategy.execute(data) # 使用例 data = [5, 3, 8, 1] context = Context(ConcreteStrategyA()) print("Ascending:", context.execute_strategy(data)) # 出力: # Ascending: [1, 3, 5, 8] context.set_strategy(ConcreteStrategyB()) print("Descending:", context.execute_strategy(data)) # 出力: # Descending: [8, 5, 3, 1]
実装内容の解説
- Strategy クラス:
アルゴリズムの抽象クラス。
executeメソッドが抽象メソッドとして定義されています。 - ConcreteStrategyA クラス:
Strategy を実装した具体的なクラス。
executeメソッドでデータを昇順にソートします。 - ConcreteStrategyB クラス:
Strategy を実装した具体的なクラス。
executeメソッドでデータを降順にソートします。 - Context クラス:
Strategy を保持し、実行するクラス。
set_strategyメソッドで Strategy を動的に変更し、execute_strategyメソッドで Strategy のexecuteメソッドを呼び出します。
まとめ
今回紹介した Observer、Memento、Strategy の3つのパターンは、 初心者でも比較的分かりやすく、実際の開発で役立ちそうだと感じました。 デザインパターンを使用することでソフトウェアの品質が向上するため、 今後の開発に取り入れていきたいと思います。 皆さんもぜひ、ご自身のプロジェクトで試してみてください!
参考書籍
採用情報
虎の穴ラボでは一緒に働く仲間を募集中です!
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧ください。
toranoana-lab.co.jp