使用Memento模式在.NET中创建高效的Builder

时间:2013-09-11 19:32:25

标签: c# .net domain-driven-design builder memento

我倾向于使用Builder模式构建我的域对象,以帮助维护封装并通过实体上的特定方法强制更改。 Java支持Joshua Bloch在Effective Java中描述的非常干净的模式实现,但是他的方法不能在.NET中使用,因为容器类不能访问嵌套类型的私有字段。因此,.NET中的大多数模式示例都使用构建器定义私有字段以在构造对象时存储状态,然后构建器将新对象的每个属性显式设置为其私有字段中的值。从内存和性能的角度来看,这似乎非常低效 - 特别是在处理具有许多属性的大型对象时。

在我看来,使用Memento可能是一个快乐的妥协,在克服.NET强加的限制的同时实现了Bloch的初衷。这是一个例子:

public interface ICustomerBuilder
{
    Customer Build();

    ICustomerBuilder WithName(String name);
    ICustomerBuilder WithPhoneNumber(String phoneNumber);
}

public sealed class Customer
{
    private class Builder : ICustomerBuilder
    {
        private readonly CustomerState _state;

        public Builder(Int32 code)
            : base()
        {
            _state = new CustomerState(code);
        }

        public Customer Build()
        {
            return new Customer(_state);
        }

        public ICustomerBuilder WithName(String name)
        {
            _state.Name = name;
            return this;
        }

        public ICustomerBuilder WithPhoneNumber(String phoneNumber)
        {
            _state.PhoneNumber = phoneNumber;
            return this;
        }
    }

    private class CustomerState
    {
        public CustomerState(Int32 code)
            : base()
        {
            Code = code;
        }

        public Int32 Code { get; private set; }
        public String Name { get; set; }
        public String PhoneNumber { get; set; }
    }

    private CustomerState _state;

    private Customer(CustomerState state)
        : base()
    {
        _state = state;
    }

    public Int32 Code
    {
        get { return _state.Code; }
    }

    public String Name
    {
        get { return _state.Name; }
        private set { _state.Name = value; }
    }

    public String PhoneNumber
    {
        get { return _state.PhoneNumber; }
        private set { _state.PhoneNumber = value; }
    }

    public void ChangeName(String newName)
    {
        Name = newName;
    }

    public static ICustomerBuilder CreateNew(Int32 code)
    {
        return new Builder(code);
    }
}

这是一个可行的解决方案还是有更好的方法来实现相同的目标?

这似乎也可以帮助实现撤消场景,因为我的域对象已经使用Memento作为其当前状态。我还假设验证和变更管理仍然会在Memento只是一个DTO的实体中发生。

思想?

0 个答案:

没有答案