有帮助吗?

解决方案

通常情况下,你不希望引入到持久化你的域对象,因为它不是商业模式的一部分(飞机不构造本身,它飞乘客/货物从一个地方到另一个)。您应该使用库模式,一个的 ORM框架或一些其他数据访问模式来管理对象的状态的持久存储和retreival。

凡贫血域模型也发挥了作用是当你正在做的事情是这样的:

IAirplaneService service = ...;
Airplane plane = ...;
service.FlyAirplaneToAirport(plane, "IAD");

在这种情况下,飞机的状态管理(无论是飞行,在那里它在,什么发车时间/机场,什么是到达时间/机场,有什么飞行计划等)委托给一些外部平面...的AirplaneService实例。

实现,这将是设计您接口这样的方式POCO:

Airplane plane = ...;
plane.FlyToAirport("IAD");

这是更容易发现,因为开发商知道去哪里找,使飞机飞(只是告诉飞机这样做)。它还允许您以确保状态的只有的内部管理。然后,您可以使之类的东西的当前位置为只读,并确保它在一个地方才改变。与贫血域对象,因为状态被设置在外部,发现其中状态改变变得越来越困难作为您域规模增大。

其他提示

我想澄清这最好的方法是通过定义:

<强> DTO:数据传输对象:

它们仅用于数据传输典型地表示层和服务层之间。无外乎以上。通常它被实现为具有获取并设置类。

public class ClientDTO
{
    public long Id {get;set;}
    public string Name {get;set;}
}

<强> BO:业务对象:

业务对象代表的商业元素和自然是最好的做法说,他们应该包含业务逻辑也。如通过迈克尔草甸说,它也是好的做法来隔离该对象中的数据的访问。

public class Client
{
    private long _id;
    public long Id 
    { 
        get { return _id; }
        protected set { _id = value; } 
    }
    protected Client() { }
    public Client(string name)
    {
        this.Name = name;    
    }
    private string _name;
    public string Name
    {
        get { return _name; }
        set 
        {   // Notice that there is business logic inside (name existence checking)
            // Persistence is isolated through the IClientDAO interface and a factory
            IClientDAO clientDAO = DAOFactory.Instance.Get<IClientDAO>();
            if (clientDAO.ExistsClientByName(value))
            {
                throw new ApplicationException("Another client with same name exists.");
            }
            _name = value;
        }
    }
    public void CheckIfCanBeRemoved()
    {
        // Check if there are sales associated to client
        if ( DAOFactory.Instance.GetDAO<ISaleDAO>().ExistsSalesFor(this) )
        {
            string msg = "Client can not be removed, there are sales associated to him/her.";
            throw new ApplicationException(msg);
        }
    }
}

<强>服务或应用程序类 这些类表示用户和该系统之间的交互,他们将利用两个ClientDTO和客户端的

public class ClientRegistration
{
    public void Insert(ClientDTO dto)
    {
        Client client = new Client(dto.Id,dto.Name); /// <-- Business logic inside the constructor
        DAOFactory.Instance.Save(client);        
    }
    public void Modify(ClientDTO dto)
    {
        Client client = DAOFactory.Instance.Get<Client>(dto.Id);
        client.Name = dto.Name;  // <--- Business logic inside the Name property
        DAOFactory.Instance.Save(client);
    }
    public void Remove(ClientDTO dto)
    {
        Client client = DAOFactory.Instance.Get<Client>(dto.Id);
        client.CheckIfCanBeRemoved() // <--- Business logic here
        DAOFactory.Instance.Remove(client);
    }
    public ClientDTO Retrieve(string name)
    {
        Client client = DAOFactory.Instance.Get<IClientDAO>().FindByName(name);
        if (client == null) { throw new ApplicationException("Client not found."); }
        ClientDTO dto = new ClientDTO()
        {
            Id = client.Id,
            Name = client.Name
        }
    }
}

我个人不觉得那些贫血的领域模型如此糟糕;我真的很喜欢具有仅代表数据,而不是行为域对象的想法。我觉得这种方法的主要缺点是代码的可发现性;你需要知道,可使用它们哪些动作。要解决这个问题,仍然保持从模型中分离行为代码的方法之一是引入了行为的接口:

interface ISomeDomainObjectBehaviour
{
    SomeDomainObject Get(int Id);
    void Save(SomeDomainObject data);
    void Delete(int Id);
}

class SomeDomainObjectSqlBehaviour : ISomeDomainObjectBehaviour
{
    SomeDomainObject ISomeDomainObjectBehaviour.Get(int Id)
    {
        // code to get object from database
    }

    void ISomeDomainObjectBehaviour.Save(SomeDomainObject data)
    {
        // code to store object in database
    }

    void ISomeDomainObjectBehaviour.Delete(int Id)
    {
        // code to remove object from database
    }
}
class SomeDomainObject
{
    private ISomeDomainObjectBehaviour _behaviour = null;
    public SomeDomainObject(ISomeDomainObjectBehaviour behaviour)
    {

    }

    public int Id { get; set; }
    public string Name { get; set; }
    public int Size { get; set; }


    public void Save()
    {
        if (_behaviour != null)
        {
            _behaviour.Save(this);
        }
    }

    // add methods for getting, deleting, ...

}

这样,你可以继续从模型中分离出来的行为实施。使用接口实现的被注射到模型中也使代码而易于测试,因为可以很容易地嘲笑的行为。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top