当前位置:  开发笔记 > 编程语言 > 正文

在OO中建模的一对一关系

如何解决《在OO中建模的一对一关系》经验,为你挑选了1个好方法。

在软件系统中,必须在两个对象之间建立一对一的关系,其中存在关系的活动状态.

换句话说,ObjectA与ObjectB(没有后向指针)具有一对一的关系,其中关系可以是活动的或非活动的.可能还存在与关系相关联的其他属性.

在.NET中使用面向对象建模此场景的最佳方法是什么?



1> Raymond Roes..:

这取决于激活关系是否是您要建模的系统行为的一部分.

"可能还有其他与这种关系相关的属性."

所以这听起来像你想要的模型不仅仅是一个参考.包含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 where TDestination :class
    {
        private bool active = true;
        private readonly TDestination destination;

        public UniDirectionalRelationship(TDestination destination)
        {
            if(destination == null)
            {
                throw new ArgumentNullException("destination","destination cannot be null");
            }
            this.destination = destination;
        }
        public void Activate()
        {
            active = true;
        }
        public void Deactivate()
        {
            active = false;
        }

        public virtual bool IsActive
        {
            get { return active; }
        }

        public virtual TDestination Destination
        {
            get
            {
                if (active)
                {
                    return destination;
                } 
                throw new RelationshipNotActiveException("the relationship is not active");
            }
        }

        public virtual object Source
        {
            get { throw new NotSupportedException("Source is not supported"); }
        }
    }
}

推荐阅读
我我檬檬我我186
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有