MENU

詳細設計のデザインパターン

目次

調査に至った背景

先日、練習用Webアプリの開発で、基本設計を行い、詳細設計を行っております。geeksforgeeksによると、詳細設計にはいくつか抑えなければいけないポイントがあり、その中の一つがデザインパターンだそうです。ちなみに、最初聞いたときはMVCパターンとかの話?と思いましたが、そういうわけでありません。

geeksforgeeksを読んだ限りでは、保守性や可読性を向上させるための、クラスのデザインパターン、という印象を受けました。今回は、基本のデザインパターンを4つ学習し、練習用Webアプリの開発で、使えそうなパターンとなぜそう考えたのか、をまとめました。
※自分のアプリに適用できそうな点を考えるのに時間がかかっているため、いったん調査結果のみで公開します

デザインパターン(4種類)の調査

geeksforgeeksの詳細設計に関する記事を読んだところ、基本になるデザインパターンは4種類あります。詳細は下記のリンク内に書かれているため、ここでは、どんな問題を解消できるか、という点に絞って説明します。

Factory Design Pattern

Factory Design Patternは、オブジェクトのインスタンス化をするためのクラスを作成することによって、他のクラスに与える影響を0にするための方法です。

例えば、携帯電話をプロパティにもつユーザークラスについて考えます。ユーザークラスをコードにすると、こんな感じになります。

## Factory実装前

class User{

    public Phone Phone;

    public User(int PhoneType){
        switch(PhoneType){
            case Phone.enum.FlipPhone:
                Phone = FlipPhone();
                break;
            case Phone.enum.Android:
                Phone = SmartPhone();
                break;
            case Phone.enum.IPhone:
                Phone = IPhone();
                break;
            default:
                Phone = Phone();            
        }
    }
}

abstract class Phone{    

    enum{
        FlipPhone=1,
        Android=2,
        IPhone=3
    }
}


// ガラケー
class FlipPhone : Phone{

}

class Android : Phone{

}

class IPhone : Phone{

}

上記のコードでは、携帯電話の種類が増えるたびにユーザークラスのコードに手を加える必要が生じます。そこで、携帯電話クラスをインスタンス化する部分を担当するPhoneFactoryクラスを実装します。

class User{

    public Phone Phone;

    public User(int phoneType){
        Phone = PhoneFactory.GetPhone(phoneType);
    }
}


class PhoneFactory{

    static Phone GetPhone(int phoneType){
        switch(phoneType){
            case Phone.enum.FlipPhone:
                return FlipPhone();                
            case Phone.enum.SmartPhone:
                return SmartPhone();                
            case Phone.enum.IPhone:
                return IPhone();                
            default:
                return Phone();            
        }        
    }
}

// Phoneとその派生クラスは同様

上記のようにすることによって、Phoneの派生クラスの追加や削除が生じた際、PhoneFactoryを変更することによって、Userクラスを修正せずに対応することができます。

Abstract Factory Pattern

Abstract Factory Patternとは

Abstract Factory Patternは名前の通りで、Factory Patternについて、抽象的 (abstract) なFactoryクラスとそれを継承した具体的 (concrete) なFactoryクラスを追加したものになります。そのため、Factoryクラスと同様に、オブジェクトのインスタンス化をするためのクラスを作成することによって、他のクラスに与える影響を0にするための方法です。

おそらく、Abstract Factory PatternとFactory Patternの使い分けは、対象オブジェクトの複雑さに関係します。例えば、上記のコードに対して、さらにGalaxyやIPhoneXのような具体的な派生クラスが追加された場合です。Factoryクラス一つで、AndroidとIPhoneの両方を網羅するのに比べ、AndroidFactoryクラスとIPhoneFactoryクラスを派生クラスとして設けることによって、その後の改修時の影響範囲をより限定的にすることができます。以下、コードの例となります。

class PhoneFactory{

    Phone GetPhone(int PhoneType){
        switch(PhoneType){
            case Phone.enum.FlipPhone:
                return FlipPhone();                
            case Phone.enum.Android:
                return Android();                
            case Phone.enum.IPhone:
                return IPhone();                
            default:
                return Phone();            
        }        
    }
}

// ANdroidクラスをインスタンス化するためのFactoryクラス
class AndroidFactory : PhoneFactory{

    Phone GetPhone(int AndroidType){
        switch(AndroidType){
            case Android.enum.Galaxy:
                return Galaxy();                
            case Android.enum.Pixel:
                return Android();                            
            default:
                return Android();            
        }        
    }
}

class IPhoneFactory : PhoneFactory{

    Phone GetPhone(int IPhoneType){
        switch(IPhoneType){
            case IPhone.enum.IPhoneSE:
                return IPhoneSE();                
            case IPhone.enum.IPhone5s:
                return IPhone5s();                            
            default:
                return IPhone();            
        }        
    }
}


## 携帯電話に関するクラス

abstract class Phone{    
    enum{
        FlipPhone=1,
        Android=2,
        IPhone=3
    }
}


// ガラケー
class FlipPhone : Phone{
    
}

class Android : Phone{    
    enum{
        Galaxy=1,
        Pixel=2
    }
}

class Galaxy : Android{

}

class Pixel : Android{

}

class IPhone : Phone{
    enum{
        IPhoneSE=1,
        IPhone5s=2
    }
}

class IPhoneSE : IPhone{

}

class IPhone5s : IPhone{
    
}

採用が推奨される事例

geeksforgeeksでは、推奨される場合を4つ挙げております。

geeksforgeeks, “Abstract Factory Pattern” 拙訳
  • オブジェクトに複数の派生クラスがある場合 :

参考文献

geeksforgeeks, “Abstract Factory Pattern“, 最終更新日 : 2024年2月6日

Singleton Pattern

singleton は単独で活動する人[物]という意味で、Singleton Patternは、あるクラスから複数のインスタンスを生成することを制限するための、デザインパターンです。

Singleton patternを実装する方法は複数ありますが、以下のメンバを持つことが一般的な特徴です。

  • アクセス修飾子がprivateで引数をもたないコンストラクタ
  • Sealed修飾子をもつclass
  • 生成された唯一のインスタンスの参照を持つstatic変数
  • アクセス修飾子がpublicで、生成されたインスタンスへの参照を取得する静的なメソッド

クラス図にすると、以下のようになります。

参考文献
C# Corner, “Singleton Design Pattern In C#“, 最終更新日 : 06/06/2023

Observer Design Pattern

Observer Design Pattern

Observer Design Pattern は、オブジェクト間の1対nの依存性を定義します。依存性を定義することによって、1つのオブジェクトの状態が変化したとき、依存関係にあるすべてのオブジェクトは状態の変化を知らされ、自動的に更新することができます。

参考文献
geeksforgeeks, “Observer Design Pattern“, 最終更新日 : 2024年2月6日

Observer Design Patternは、Subject, Observer, ConcreteSubject, ConcreteObserverの4つの要素から構成されます。上記の定義でいうところの、Subject(対象)が1で、Observer(観察者)がnになります。そのため、Subjectの状態の変化を、Observerが検知し、対応するプロパティの値を変更します。また、Concrete~はそれぞれの派生クラスを表します。

参考文献
geeksforgeeks, “ObserverDesignPattern“, 最終更新日 : 06/02/2024

考察

練習用Webアプリ (WOB) で利用できると考えているデザインパターンは、Abstract Factory Patternです。WOBの要件の一つに、「チーム内で予定を共有できること」があるため、予定に関するCRUD機能を実装する必要があります。予定は、試合や移動、打ち合わせ等、いくつか種類があり、さらにそれは今後増えていくことを予想しております。

以下、予定(Event)クラスに関するクラス図になります。EventFactoryクラスの派生クラスとして、GameFactory, MeetingFactory, TransferFactoryクラスを用意しました。

感想

詳細設計のデザインパターンについて、代表的な4つを学習しました。それぞれの使いどころや長所・短所を抑えることによって、強力なツールになることを感じました。今回は、代表的な4つでしたが、少しずつ勉強することによって、他のデザインパターンについても使えるようになっていきたいです。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

CAPTCHA


目次