0

私の現在のサービスおよびビジネスレイヤーの実装は、次のように簡単です。

public class MyEntity { }

// Business layer
public interface IBusiness { IList<MyEntity> GetEntities(); }
public class MyBusinessOne : IBusiness
{
    public IList<MyEntity> GetEntities()
    {
        return new List<MyEntity>();
    }
}

//factory
public static class Factory
{
    public static T Create<T>() where T :  class
    {
        return new MyBusinessOne() as T; // returns instance based on T
    }
}

//Service layer
public class MyService
{
    public IList<MyEntity> GetEntities()
    {
        return Factory.Create<IBusiness>().GetEntities();
    }
}

現在の実装にいくつかの変更が必要でした。データである理由は時間の経過とともに増大し、サービスとクライアントは大量のデータを処理できません。現在のサービスにページ付けを実装する必要がありました。また、いくつかの機能(データがしきい値を超えた場合のリターン障害、フィルターの適用など)も期待されるため、設計を更新する必要があります。

以下は私の新しい提案です。

public interface IBusiness
{
    IList<MyEntity> GetEntities();
}

public interface IBehavior
{
    IEnumerable<T> Apply<T>(IEnumerable<T> data);
}

public abstract class MyBusiness
{
    protected List<IBehavior> Behaviors = new List<IBehavior>();
    public void AddBehavior(IBehavior behavior)
    {
        Behaviors.Add(behavior);
    }
}

public class PaginationBehavior : IBehavior
{
    public int PageSize = 10;
    public int PageNumber = 2;
    public IEnumerable<T> Apply<T>(IEnumerable<T> data)
    {
        //apply behavior here
        return data
            .Skip(PageNumber * PageSize)
            .Take(PageSize);
    }
}

public class MyEntity { }

public class MyBusinessOne : MyBusiness, IBusiness
{
    public IList<MyEntity> GetEntities()
    {
        IEnumerable<MyEntity> result = new List<MyEntity>();
        this.Behaviors.ForEach(rs =>
        {
            result = rs.Apply<MyEntity>(result);
        });
        return result.ToList();
    }
}

public static class Factory
{
    public static T Create<T>(List<IBehavior> behaviors) where T : class
    {
        // returns instance based on T
        var instance = new MyBusinessOne();
        behaviors.ForEach(rs => instance.AddBehavior(rs));
        return instance as T;
    }
}

public class MyService
{
    public IList<MyEntity> GetEntities(int currentPage)
    {
        List<IBehavior> behaviors = new List<IBehavior>() { 
            new PaginationBehavior() { PageNumber = currentPage, }
        };
        return Factory.Create<IBusiness>(behaviors).GetEntities();
    }
}

専門家は、私の実装が正しいか、それとも私がそれを殺しすぎているかどうかを私に提案してください。それがどのデザインパターンであるかを修正する場合-デコレータまたはビジター。

また、私のサービスはJSON文字列を返します。この動作コレクションを使用して、エンティティ全体ではなく、選択したプロパティのみをシリアル化するにはどうすればよいですか。プロパティのリストは、リクエストとしてユーザーから提供されます。(カラムピッカーの種類)

4

1 に答える 1

1

あなたの質問にコメントするのに十分なポイントがないようです。私は C# の専門家ではないので、いくつかの仮定を立てます。

仮定 1: 最初にデータを取得してから、動作オブジェクトを使用してページネーションを適用しているように見えます。もしそうなら、これは間違ったアプローチです。500 件のレコードがあり、フェッチごとに 50 件のレコードを表示しているとします。単純に DB から 50 レコードをフェッチする代わりに、500 レコードを 10 回フェッチし、その上にコストのかかるフィルターを追加しています。DB は、C# や Java よりもこの仕事を行うのに適しています。

ページネーションをサービスに関する振る舞いとは考えません。プレゼンテーション層の動作です。あなたのサービスは「データの粒度」だけを気にするべきです。顧客の 1 人が一度にすべてのデータを必要としているように見えますが、他の顧客はそのデータのサブセットを必要としている可能性があります。

オプション 1: DAO 層で、2 つのメソッドを用意します。1 つはページネーション用で、もう 1 つは通常のフェッチ用です。着信パラメーターに基づいて、呼び出すメソッドを決定します。

オプション 2: サービス レベルで 2 つのメソッドを作成します。1 つはデータの小さなサブセット用で、もう 1 つはデータ セット全体用です。JSONと言ったので、これはRestfulサービスのはずです。次に、着信 URL に基づいて、適切なメソッドを適切に呼び出します。Jersey を使用している場合、これは簡単なはずです。

サービスでは、新しいメソッドを公開するか、既存のメソッド/機能に新しいパラメーターを追加するだけで、新しい動作を追加できます (これらの変更が下位互換性があることを確認してください)。Decorator や Visitor パターンは本当に必要ありません。唯一の懸念事項は、既存のユーザーが影響を受けないことです。

于 2013-02-08T17:19:16.433 に答える