Отношения один к одному, смоделированные в ОО - PullRequest
2 голосов
/ 25 января 2009

В программной системе отношение один к одному должно моделироваться между двумя объектами, для которых существует активный статус отношения.

Другими словами, ObjectA имеет однозначное отношение к ObjectB (без обратного указателя), где отношение может быть либо активным, либо неактивным. Также могут быть дополнительные атрибуты, связанные с отношением.

Каков наилучший способ моделирования этого сценария с использованием объектной ориентации в .NET?

Ответы [ 3 ]

9 голосов
/ 25 января 2009

Зависит от того, является ли активация отношения частью поведения системы, которую вы хотите смоделировать.

"Также могут быть дополнительные атрибуты, связанные с отношением."

Так что звучит так, будто вы хотите смоделировать больше, чем просто ссылку. Содержащий экземпляр b будет работать в простых ситуациях, когда взаимосвязь не является частью поведения системы, а является лишь технической реализацией.

Если вы хотите активировать / деактивировать / активировать (без знания / запоминания активированного объекта B), «нулевое моделирование» не будет работать (потому что вы потеряли бы ссылку и потеряли бы информацию о взаимосвязи). Или, например, когда на более позднем этапе вы захотите повторно активировать отношения без ссылки на a и b, но на отношения. Таким образом, видя отношения как первоклассный гражданин модели.

Затем вы можете сделать что-то вроде этого (но это может быть излишним, и просто показать моделирование отношений как часть вашего домена):

alt text
(источник: 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<TSource,TDestination> : 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<ObjectB> relation;

        public ObjectBProxy(ObjectB to)
        {
            this.relation = new UniDirectionalRelationship<ObjectB>(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<TDestination> : IRelationShip<object,TDestination> 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"); }
        }
    }
}
3 голосов
/ 25 января 2009

ObjectA, содержащий экземпляр ObjectB. Неактивное обозначается как нулевое значение, в противном случае оно активно.

0 голосов
/ 25 января 2009

Я думаю, что вы хотите, чтобы назывались объективированные отношения или объективированные ассоциации. По сути, ваши отношения - это объект первого класса, который может иметь свойства, состояния и т. Д. *

Зацените это сообщение в блоге от Kyle Baley. В его случае он говорит об ассоциациях «многие ко многим», но я думаю, что модель может работать и в отношениях один к одному. Обязательно прочитайте и комментарии блога.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...