1

私は最終日、どのパターンが自分の特定のシナリオに最も適しているかを考えようとしましたが、State パターンと Strategy パターンの間を行き来しました。私がインターネットで例を読んだとき、それは完全に理にかなっています... しかし、実際にそれを自分の問題に適用しようとするのは別のスキルです. 私のシナリオと直面している問題について説明します。うまくいけば、誰かが私を正しい方向に向けることができます.

問題: さまざまな同期状態 (最新、古い、未公開、未公開など) を持つベース オブジェクトがあります。オブジェクトの状態によって動作が異なります。たとえば、ベース オブジェクトの最新バージョンを取得できません。それは公開されたことがない。この時点で、State 設計パターンが最も適しているように思えます...それを実装したところ、各状態に CanGetLatestVersion、GetLatestVersion、CanPublish、Publish などのメソッドが含まれるようになりました。

この時点ですべてが良さそうです。しかし、基本クラスから派生した10個の異なる子オブジェクトがあるとしましょう...各状態に対して「公開」メソッドが実行されると、実際に操作を実行するには子オブジェクトのプロパティが必要ですが、各状態が必要になるため、私のソリューションは壊れていますベースオブジェクトへの参照のみがあります。C# での問題を説明するサンプル プロジェクトの作成に時間を費やしました。

public class BaseDocument
{
    private IDocumentState _documentState;

    public BaseDocument(IDocumentState documentState)
    {
        _documentState = documentState; 
    }

    public bool CanGetLatestVersion()
    {
        return _documentState.CanGetLatestVersion(this); 
    }

    public void GetLatestVersion()
    {
        if(CanGetLatestVersion())
            _documentState.CanGetLatestVersion(this); 
    }

    public bool CanPublish()
    {
        return _documentState.CanPublish(this);
    }

    public void Publish()
    {
        if (CanPublish())
            _documentState.Publish(this);
    }

    internal void Change(IDocumentState documentState)
    {
        _documentState = documentState; 
    }
}

public class DocumentSubtype1 : BaseDocument
{
    public string NeedThisData { get; set; }
}

public class DocumentSubtype2 : BaseDocument 
{
    public string NeedThisData1 { get; set; }
    public string NeedThisData2 { get; set; }
}

public interface IDocumentState
{
    bool CanGetLatestVersion(BaseDocument baseDocument);
    void GetLatestVersion(BaseDocument baseDocument);
    bool CanPublish(BaseDocument baseDocument);
    bool Publish(BaseDocument baseDocument);
    SynchronizationStatus Status { get; set; }     
}

public class LatestState : IDocumentState
{
    public bool CanGetLatestVersion(BaseDocument baseDocument)
    {
        return false; 
    }

    public void GetLatestVersion(BaseDocument baseDocument)
    {
        throw new Exception(); 
    }

    public bool CanPublish(BaseDocument baseDocument)
    {
        return true; 
    }

    public bool Publish(BaseDocument baseDocument)
    {
        //ISSUE HERE... I need to access the properties in the the DocumentSubtype1 or DocumentSubType2 class. 
    }

    public SynchronizationStatus Status
    {
        get
        {
            return SynchronizationStatus.LatestState; 
        }
    }
}

public enum SynchronizationStatus
{
    NeverPublishedState, 
    LatestState,
    OldState,
    UnpublishedChangesState,
    NoSynchronizationState
}

次に、各子オブジェクトの状態を実装することを考えました...これはうまくいきますが、50個のクラス、つまり(10個の子 x 5個の異なる状態)を作成する必要があり、それはまったくクレイジーに思えます...なぜ私はここにいるのですか?

どんな助けでも大歓迎です。わかりにくい場合はお知らせください。明確にすることができます。

乾杯

4

2 に答える 2

0

この種のアーキテクチャの問題には、多くの設計パターンを使用できます。パブリッシュの方法の例を挙げていないのは残念です。ただし、いくつかの優れたデザインについて説明します。

  1. 追加のパラメーターをベース ドキュメントに配置し、null 可能にします。ドキュメントで使用されていない場合は null です。そうでなければ、価値があります。ここでは継承は必要ありません。

  2. Publish メソッドを に配置しないでください。代わりにDocumentStateを配置して ください。論理的には、Publish メソッドは DocumentState ではなくBaseDocument一部である必要があります。BaseDocument

  3. パブリッシング(パブリッシャー サービス)は、他のサービス クラスに任せます。抽象ファクトリパターンを使用して実現できます。このように、1:1 のドキュメント: 発行者オブジェクトを作成する必要があります。多いかもしれませんが、各ドキュメントの発行者を自由に変更できます。

    public interface IPublisher<T> where T : BaseDocument
    {
        bool Publish(T document);
    }
    
    public interface IPublisherFactory
    {
        bool Publish(BaseDocument document);
    }
    
    public class PublisherFactory : IPublisherFactory
    {
        public PublisherFactory(
            IPublisher<BaseDocument> basePublisher
            , IPublisher<SubDocument1> sub1Publisher)
        {
            this.sub1Publisher = sub1Publisher;
            this.basePublisher = basePublisher;
        }
        IPublisher<BaseDocument> basePublisher;
        IPublisher<SubDocument1> sub1Publisher;
    
        public bool Publish(BaseDocument document)
        {
            if(document is SubDocument1)
            {
                return sub1Publisher.Publish((SubDocument1)document);
            }
            else if (document is BaseDocument)
            {
                return basePublisher.Publish(document);
            }
            return false;
        }
    }
    
    public class LatestState : IDocumentState
    {
        public LatestState(IPublisherFactory factory)
        {
            this.factory = factory;
        }
        IPublisherFactory factory;
    
        public bool Publish(BaseDocument baseDocument)
        {
            factory.Publish(baseDocument);
        }
    }
    
  4. 継承よりも構成を使用します。各状態への各インターフェイスを設計し、それをドキュメントに構成します。要約するCanGetLatestVersionと、構成クラスは 5 つと他の構成クラスを使用できますが、発行者の構成クラスは 10 です。

  5. より高度に、使用するリポジトリに基づいて、おそらくVisitor pattern. このようにして、各公開方法を自由に変更できます。1 つのクラスで宣言されていることを除いて、ポイント 3 に似ています。例えば:

    public class BaseDocument
    {
    
    }
    public class SubDocument1 : BaseDocument
    {
    
    }
    
    public class DocumentPublisher
    {
        public void Publish(BaseDocument document)
        {
    
        }
        public void Publish(SubDocument1 document)
        {
            // do the prerequisite
            Publish((BaseDocument)document);
            // do the postrequisite
        }
    }
    

他のデザインも利用できる場合がありますが、リポジトリへのアクセス方法によって異なります。

于 2013-05-06T02:01:07.100 に答える