向现有实现添加行为 - C#/ Design Pattern

时间:2013-02-07 17:12:28

标签: c#-4.0 design-patterns

我目前对服务和业务层的实施很简单,如下所示。

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字符串。如何使用此行为集仅序列化选定的属性而不是整个实体。属性列表来自用户作为请求。 (列选择器的种类)

1 个答案:

答案 0 :(得分:1)

看起来我没有足够的观点来评论你的问题。所以,我会做一些假设,因为我不是C#专家。

假设1:看起来您首先获取数据然后使用行为对象应用分页。如果是这样,这是一种错误的方法。让我们说有500条记录,你每次获取显示50条记录。您不是简单地从数据库中提取50条记录,而是提取500条记录10次,而在此基础上您将添加一个昂贵的过滤器。 DB能够更好地完成C#或Java这项工作。

我不会将分页视为与服务相关的行为。它是表示层的行为。您的服务应该只担心'数据粒度'。看起来您的一个客户想要一次性获取所有数据,而其他人可能想要该数据的子集。

选项1:在DAO层中,有两种方法:一种用于分页,另一种用于常规提取。根据传入的params决定调用哪种方法。

选项2:在服务级别创建两个方法。一个用于一小部分数据,另一个用于整个数据集。既然你说JSON,这应该是Restful服务。然后根据传入的URL,正确调用正确的方法。如果你使用泽西岛,这应该很容易。

在服务中,可以通过简单地公开新方法或向现有方法/功能添加新参数来添加新行为(只需确保这些更改向后兼容)。我们真的不需要装饰器或访客模式。唯一的问题是不应该影响现有用户。