在软件系统中,必须在两个对象之间建立一对一的关系,其中存在关系的活动状态.
换句话说,ObjectA与ObjectB(没有后向指针)具有一对一的关系,其中关系可以是活动的或非活动的.可能还存在与关系相关联的其他属性.
在.NET中使用面向对象建模此场景的最佳方法是什么?
这取决于激活关系是否是您要建模的系统行为的一部分.
"可能还有其他与这种关系相关的属性."
所以这听起来像你想要的模型不仅仅是一个参考.包含b的实例将在简单的情况下工作,其中关系不是系统行为的一部分,而只是技术实现.
如果要激活/取消激活/激活(不知道/记住对象B已激活),"空建模"将不起作用(因为您将丢失该引用,并且您将丢失有关该关系的信息).或者例如,在稍后阶段,您希望重新激活关系,而不是引用a和b,而是关系.因此,将这种关系视为该模型的一等公民.
然后你可以做这样的事情(但这可能是完全矫枉过正的,只是为了显示关系的建模作为你域的一部分):
(来源:googlecode.com)
objectA使用ObjectB代理,它将充当ObjectB,但它实际上引用了与ObjectB的单向关系.ObjectB代理可以实现关系不活动时要执行的操作.
在代码中:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ActivatableRelationshipExample { public interface IActivatable { void Activate(); void Deactivate(); bool IsActive { get; } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ActivatableRelationshipExample { public interface IRelationShip: IActivatable { TDestination Destination { get; } TSource Source { get; } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ActivatableRelationshipExample { public class ObjectA { // you could also have an ObjectB reference here // and fill it with an ObjectBProxy instance // in the constructor. thought this would // explain the example a bit better private readonly ObjectBProxy proxy; public ObjectA(ObjectB b) { proxy = new ObjectBProxy(b); } public void AMethodUsingB() { proxy.BMethod(); } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ActivatableRelationshipExample { public class ObjectB { public virtual void BMethod() { } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ActivatableRelationshipExample { public class ObjectBProxy : ObjectB, IActivatable { private readonly UniDirectionalRelationship relation; public ObjectBProxy(ObjectB to) { this.relation = new UniDirectionalRelationship (to); } public override void BMethod() { if (relation.IsActive) { relation.Destination.BMethod(); } else { // do some specific logic here } } public void Activate() { relation.Activate(); } public void Deactivate() { relation.Deactivate(); } public bool IsActive { get { return relation.IsActive; } } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ActivatableRelationshipExample { public class RelationshipNotActiveException : Exception { public RelationshipNotActiveException(string message) : base(message) { } public RelationshipNotActiveException(string message, Exception innerException) : base(message, innerException) { } } } using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ActivatableRelationshipExample { public class UniDirectionalRelationship : IRelationShip