2012-01-06 3 views
4

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

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

Это пример, на стадионе Yankee проводятся игры в бейсбол, хоккей и футбол. Я хочу, чтобы он реализовал каждый из этих трех интерфейсов. The StadiumBaseClass - мой абстрактный базовый класс, который взаимодействует с моей базой данных. The 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;} } 
} 
+0

Можете ли вы ознакомиться с шаблоном абстрактного завода и посмотреть, похоже ли это на то, что вам нужно. –

+0

Итак, 'StadiumBaseClass' ваш« абстрактный базовый класс », как говорит ваше описание, или объект данных, который инкапсулирует все стадионы, как показывает ваш код? – dasblinkenlight

+0

Вы C# 4.0 или до 4.0? – dasblinkenlight

ответ

0

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

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

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

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

Мне нужно было бы отправить на интерфейс inorder, чтобы вызвать метод Whatever(). – Mark

+0

Да, с унаследованным классом, но вы также можете выставить выбранные методы интерфейса в качестве конкретных методов в базовом классе, если им нужен класс наследования. Поверхность заключается в том, что этот метод позволяет исключить избыточный возврат данных базового класса из класса наследования, который вы указали в своем вопросе. Этот код будет реализован непосредственно на стадионбассейне и не должен повторяться в его наследниках. –

+0

Конечно, было бы полезно, если бы downvoters объясняли бы их логику. Ниспровержение без объяснений никому не помогает и, откровенно говоря, трусливо. –

-1

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

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

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

2

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

Аналогичным образом у вас должны быть такие свойства, как HasHockey ИЛИ просто вернуть свойство хоккея null, если оно неприменимо.

+0

В моем примере нет наследования ... Я могу сделать, если (объект IHockey), чтобы определить, имеет ли на холле информацию о хоккее. У меня нет собственности. – Mark

1

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

Stadium.Baseball.Fixtures 
Stadium.Hockey.Teams 

Когда конкретный стадион не позволяет спорта, вернуть Null Object, который для этого вида спорта;

например

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

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

((IBaseball)stadium).Fixtures 
2

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

Лучшим решением, которое я видел, является тот, который был предложен Peter Coad и Jeff De Luca как Nebulon Archetypal Domain Shape, также известный как Color Modelling.

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

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

+0

Я также рекомендовал бы развязать уровень доступа к данным из бизнес-уровня.Если бизнес-логика довольно абстрактна, а сущности db сильно нормализованы, попытка объединить DAL и BL, скорее всего, закончится кодовым беспорядком. –

+0

Я намерен/уже отделил данные от бизнес-уровня. – Mark