Это плохая практика иметь класс, который требует ссылки на экземпляр объекта? - PullRequest
4 голосов
/ 05 декабря 2009

Я видел это в чьем-то коде и думал: «Это элегантный способ решения этой конкретной проблемы, но, вероятно, он эпическим образом нарушает хорошие принципы ОО».

В конструкторе для набора классов, которые все являются производными от общего базового класса, он требует, чтобы была передана ссылка на экземплярный класс. Например,
Foo Foo_i = new (this);

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

С одной стороны, это упрощает ТОНН кода, который моделирует 5-уровневую древовидную структуру аппаратного обеспечения (агенты подключаются к портам на нескольких коммутаторах и т. Д.). С другой стороны, эти объекты довольно тесно связаны друг с другом, что кажется неправильным, но я не знаю достаточно о OOA & D, чтобы понять, как это сделать.

Итак, это хорошо? Или это ОО-эквивалент оператора goto?

Ответы [ 5 ]

5 голосов
/ 06 декабря 2009

Вы должны стараться избегать взаимных ссылок (особенно при реализации сдерживания), но зачастую их невозможно избежать. То есть отношения родитель-ребенок - дети часто должны знать родителя и уведомлять его, если происходят какие-то события. Если вам действительно нужно это сделать - выберите интерфейсы (или абстрактные классы в случае C ++). Таким образом, ваш экземпляр класса должен реализовывать некоторый интерфейс, а экземпляр класса должен знать его только как интерфейс - это значительно уменьшит связь. В некотором отношении этот подход аналогичен вложенному классу слушателя, поскольку он предоставляет только часть класса, но его легче поддерживать. Вот небольшой пример C #:

interface IParent
{
    //some methods here
}

class Child
{
    // child will know parent (instancing class) as interface only
    private readonly IParent parent_;
    public Child(IParent parent)
    {
        parent_ = parent;
    }
}

class Parent : IParent
{
    // IParent implementation and other methods here
}
3 голосов
/ 05 декабря 2009

Звучит так, как будто это может нарушать Закон Деметры , в зависимости от того, сколько Фу нужно знать, чтобы ловить рыбу в классе экземпляров. Объекты предпочтительно должны быть слабо связаны. Вы бы предпочли, чтобы у одного класса не было необходимости много знать о структуре другого класса. Один пример, который я слышал несколько раз, это то, что вы не передадите свой кошелек продавцу и не позволите ему ловить рыбу внутри. Ваш кошелек - это ваше дело, и вы найдете то, что вам нужно, чтобы дать клерку, и отдайте его себе. Вы можете реорганизовать свой кошелек, и никто не станет мудрее. Более слабая связь облегчает тестирование. В идеале Foo должен быть тестируемым без необходимости поддерживать сложный контекст.

2 голосов
/ 05 декабря 2009

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

Java, например, часто использует это с внутренними классами:

public class Outer {
  private class Inner {
    public Inner() {
      // has access to the members of Outer for the instance that instantiated it
    }
  }
}
1 голос
/ 05 декабря 2009

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

Вы не предоставили конкретный пример, но если класс напоминает вам goto, это, вероятно, плохая идея.

Вы сказали, что новый объект должен запросить экземпляр объекта для информации. Возможно, класс делает слишком много предположений о своей среде? Если эти предположения усложняют модульное тестирование, отладку или (не гипотетическое) повторное использование кода, то вам следует рассмотреть возможность рефакторинга.

Но если дизайн в целом экономит время разработчика, и вы не ожидаете, что в течение двух лет непригодного для жизни зверя, эта практика вполне приемлема с практической точки зрения.

1 голос
/ 05 декабря 2009

В Java я помню, как однажды избежал этого, создав подклассы определенных прослушивателей и адаптеров в моем контроллере и добавив эти прослушиватели и адаптеры в мои подклассы.

Другими словами, мой контроллер был

class p {

  private member x

  private methods

  private class q {
    // methods referencing p's private members and methods
  }

  x.setListener(new q());

}

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

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