Псевдо множественное наследование - PullRequest
4 голосов
/ 06 января 2012

У меня есть ряд объектов, которые я сопоставил с базой данных с помощью LINQ to SQL.Таблицы очень нормализованы.Я собираюсь абстрагироваться от моей проблемы.У меня есть пять центральных объектов, которые я реализовал в базе данных.Затем у меня есть ряд других объектов, которые я хочу реализовать один или все из этих пяти объектов.

Предположим, я реализую своего рода стадионный класс (подумайте о спортивных командах).Эти пять сущностей являются пятью основными видами спорта;Бейсбол, Баскетбол, Футбол, Хоккей, Футбол.Я хочу явно реализовать класс для каждого стадиона.

Это пример, на стадионе Янки проводятся игры в бейсбол, хоккей и футбол.Я хочу, чтобы он реализовал каждый из этих трех интерфейсов.StadiumBaseClass - это мой абстрактный базовый класс, который взаимодействует с моей базой данных.StadiumBaseClass реализует все 5 основных спортивных интерфейсов.Я не хочу иметь один и тот же код для реализации интерфейса IBaseball на всех возможных стадионах, я хочу, чтобы он был реализован один раз в StadiumBaseClass.

В этом примере я хочу реализовать только 3, это лучший способ сделать это?Это что-то одноцветное, но не совсем?

class YankeeStadium : IBaseball, IHockey, IFootball
{
    StadiumBaseClass _Stadium {get; set;}

   // IBaseball
   public IBaseball.Whatever {get { return _Stadium.Baseball;} }

   // IFootball
   public IFootball.Whatever {get { return _Stadium.Hockey;} }

  // IHockey
   public IHockey.Whatever {get { return _Stadium.Hockey;} }
}  

Ответы [ 5 ]

2 голосов
/ 06 января 2012

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

Лучшее решение, которое я видел, было предложено Питером Коадом и Джеффом де Лука как форма архетипического домена небулона , также известная как Цветовое моделирование .

В вашей ситуации реальные стадионы будут вашими Places. Поскольку вы хотите явно реализовать каждый стадион как класс, каждый из них будет представлять реальный физический стадион. Может быть полезно иметь общий абстрактный базовый класс. Свойства класса описывают физические характеристики стадиона, такие как фактический адрес и т. Д.

Каждый из видов спорта, которые вы хотите поддерживать (вы указали Бейсбол, Баскетбол, Футбол, Хоккей и Футбол), будет реализован как класс Role, скажем BaseballStadium, BasketballStadium, FootballStadium, HockeyStadium и SoccerStadium. Свойства в классе будут описывать конкретные характеристики в отношении размещения данного вида спорта (вместимость может варьироваться, например, от одного вида спорта к другому).

2 голосов
/ 06 января 2012

Я не думаю, что вам вообще следует использовать наследование. Вместо класса YankeeStadium у вас должен быть класс Stadium с именем name.

Аналогично, вы должны иметь такие свойства, как HasHockey, ИЛИ просто иметь свойство Hockey, возвращающее ноль, если оно неприменимо.

1 голос
/ 06 января 2012

Я бы предложил просто иметь свойства на каждом стадионе для каждого вида спорта, чтобы вы могли позвонить

Stadium.Baseball.Fixtures
Stadium.Hockey.Teams

Если на определенном стадионе не разрешен спорт, вернуть Нулевой объект , который для этого вида спорта;

например

iceRink.Baseball.Available // false
iceRink.Baseball.Fixtures // the empty list

Этот способ должен помочь вам избежать проблем множественного наследования, в частности, кода, подобного

((IBaseball)stadium).Fixtures
0 голосов
/ 06 января 2012

Вот альтернативный подход (мы использовали нечто подобное, но не уверены, насколько хорошо оно будет соответствовать вашей реализации linq):

Пусть StadiumBaseClass реализует каждый из интерфейсов с базовой функциональностью, а затем предоставляет виртуальные свойства, которые реализующие классы могут использовать, чтобы: а) указывать, какие интерфейсы он поддерживает, и б) изменять поведение по умолчанию при необходимости.

Например, предполагая следующие интерфейсы:

    public interface IBaseball
    {
        void Whatever();
    }
    public interface IHockey
    {
        void Whatever();
    }
    public interface IFootball
    {
        void Whatever();
    }
    public interface IBasketball
    {
        void Whatever();
    }
    public interface ISoccer
    {
        void Whatever();
    }

Ваш базовый класс будет выглядеть примерно так:

    public class StadiumBaseClass : IBaseball, IBasketball, IHockey, IFootball, ISoccer
    {

        #region IBaseball Members

        public virtual bool IBaseballImplemented
        {
            get
            {
                return false;
            }
        }

        void IBaseball.Whatever()
        {
            // Do something
        }

        #endregion

        #region IBasketball Members

        public virtual bool IBasketballImplemented
        {
            get
            {
                return false;
            }
        }

        void IBasketball.Whatever()
        {
            // Do something
        }

        #endregion

        #region IHockey Members

        public virtual bool IHockeyImplemented
        {
            get
            {
                return false;
            }
        }

        void IHockey.Whatever()
        {
            // Do something
        }

        #endregion

        #region IFootball Members

        public virtual bool IFootballImplemented
        {
            get
            {
                return false;
            }
        }

        void IFootball.Whatever()
        {
            // Do something
        }

        #endregion

        #region ISoccer Members

        public virtual bool ISoccerImplemented
        {
            get
            {
                return false;
            }
        }

        void ISoccer.Whatever()
        {
            // Do something
        }

        #endregion
    }

Что бы оставить ваш индивидуальный класс стадиона как:

    class YankeeStadium : StadiumBaseClass
    {
        public override bool  IBaseballImplemented
        {
            get 
            { 
                return true;
            }
        }
        public override bool IHockeyImplemented
        {
            get
            {
                return true;
            }
        }
        public override bool IFootballImplemented
        {
            get
            {
                return true;
            }
        }
    }
0 голосов
/ 06 января 2012

Я думаю, что вы должны сделать шаг назад и взглянуть на банду из четырех паттернов. Это именно та ситуация, для которой они предназначены, чтобы показать решения. Я рекомендую вам начать смотреть на шаблон посетителя. Шаблон vistior позволяет множеству элементов (в вашем случае стадионов) иметь общее поведение, выполняемое на них. Смотрите здесь: http://www.dofactory.com/Patterns/PatternVisitor.aspx

Список банд четырех шаблонов здесь: http://www.dofactory.com/Patterns/Patterns.aspx

Возможно, кто-то еще мог бы предложить другой образец, чтобы посмотреть. Возможно, шаблон декоратора тоже выглядит многообещающе. (Я не использовал шаблон декаратора раньше). Я думаю, что в конечном итоге вы должны бороться не с ОО, а с поиском опубликованных решений своего вероятного сценария.

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