以下の内容はhttps://toranoana-lab.hatenablog.com/entry/2024/09/30/120000より取得しました。


初心者がデザインパターンに入門してみた

こんにちは。虎の穴ラボのサカガミです。

今回はソフトウェア開発におけるデザインパターンについて 学習した内容を書かせていただきます。

デザインパターンとは?

デザインパターンとは、ソフトウェア設計における 一般的な問題を解決するための再利用可能な解決策のことです。 特定の問題に対する最適なアプローチを提供するテンプレートのようなもので、 共通の設計課題を解決するためのベストプラクティスがまとめられています。 経験豊富な開発者たちが直面した問題とその解決策が体系化されており、 コードの品質向上や保守性の向上に寄与します。

デザインパターンの利点

デザインパターンを使うことで、以下のような利点があります:

  • コードの再利用性: 汎用的な解決策を提供するため、同じ問題に対して使い回すことができ、コードの一貫性が保たれる
  • 可読性と理解の向上: よく知られたパターンを使うことで、他の開発者がコードを理解しやすくなる
  • 保守性の向上: パターンに従った設計は、変更や拡張がしやすくなり、バグの発生を減少させる
  • 効率的な開発: 問題解決のための時間を節約できる

デザインパターンの紹介

デザインパターンは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




以上の内容はhttps://toranoana-lab.hatenablog.com/entry/2024/09/30/120000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14