Передав это конструктору - PullRequest
2 голосов
/ 08 декабря 2011

В большинстве моих Java-приложений у меня есть класс Controller (Logic) и класс GUI. Мне обычно нужен класс Logic для вызова методов в классе GUI, и наоборот. Теперь, когда Logic создает GUI, я передаю ссылку на «this» в конструкторе, чтобы GUI мог вызывать методы в Logic. Вот пример кода.

public class Logic {
   private int num = 2;
   private final GUI gui;

   public Logic(){
       gui = new GUI(this);
   }

   public int getNum(){
      return num;
   }
}


public class GUI {
   private final Logic logic;

   public GUI(Logic logic){
      this.logic = logic;
   }

   public void calledLater(){
      int num = logic.getNum();
   }
}

У меня вопрос: это лучший ОО способ создания отношений агрегации или я испортил свой дизайн?

Ответы [ 5 ]

4 голосов
/ 08 декабря 2011

В опубликованном вами дизайне существует тесная связь между вашим пользовательским интерфейсом и вашей моделью. Это несколько осуждается при создании больших / формальных / серьезных / долгоживущих систем. Существует хорошо известная схема архитектуры интерфейса / модели архитектуры, известная как Model-View-Controller , которая решает эту проблему.

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

Кстати, я вижу в вашем коде «запах кода» : два объекта, A и B, каждый из которых содержит ссылку друг на друга. Обычно есть более желательный способ делать вещи, чем циклические ссылки. Вы можете избежать этого, имея, например, объект A, содержащий ссылку на B (и, возможно, даже «владеющий им»), и B отправляющий данные, представляющие интерес, к A посредством уведомлений или шаблона наблюдателя и т. Д. иметь какую-либо конкретную информацию об А, или даже знать, что он существует. Вуаля, меньше сопряжения в вашем дизайне, так что вы получите больше возможностей для повторного использования кода и менее хрупкую систему, которую легче изменить.

Важным и центральным шаблоном проектирования в Какао (и Cocoa Touch) является шаблон делегата. Этот шаблон предполагает использование протоколов (аналогично интерфейсам в других языках, таких как Java) для разделения производителя и потребителя информации, событий и т. Д.

Предлагаю прочитать эту превосходную справку от Apple о фундаментальных шаблонах проектирования в Cocoa Touch.

2 голосов
/ 08 декабря 2011

Передача this в класс пользовательского интерфейса сама по себе не является проблемой, если методы класса не вызываются через this, как в вашем примере.Вы вызываете getNum прямо в конструкторе GUI, чего следует избегать: ваш класс Logic может быть не готов к возвращению правильного результата.

Одна вещь, на которую стоит обратить внимание, это то, что вы соединяетеGUI к классу Logic, что может быть слишком сильным сцеплением.Вам следует рассмотреть возможность извлечения интерфейса из Logic и позволить GUI взаимодействовать только с тем, для чего он предназначен:

interface DataSourceForTheGui {
    int getNum();
}

class Logic implements DataSourceForTheGui {
    int getNum() {
        return n;
    }
}

class GUI {
    private readonly DataSourceForTheGui data;
    public GUI(DataSourceForTheGui data) {
        this.data = data;
    }
    public void display() {
        int k = data.getNum();
    }
}
1 голос
/ 08 декабря 2011

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

Однако я бы предпочел, чтобы Logic NOT создавал GUI.Если вы действительно хотите, чтобы модель и представление были отделены друг от друга, я думаю, что вы где-то создадите Logic и создадите GUI с объектом Logic.Затем, если Logic когда-либо понадобится обновить GUI по какой-либо причине, вы должны сгенерировать событие.

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

Некоторые хорошие классы для этого - java.util.EventListener и java.util.EventObject.

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

0 голосов
/ 08 декабря 2011

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

public class MainClass{

public static void main(String[] args){
l = new Logic();
g = new GUI(l);
l.setGUI(g);
}

public static Logic l;
public static GUI g;

}
0 голосов
/ 08 декабря 2011

Я бы сказал, что это будет работать, но я никогда не буду ссылаться на объект GUI из вашей бизнес-логики.

  • Я отвечу с комментариями. Что ты пытаешься сделать?
  • ваш пользователь должен проинструктировать ваш GUI, а GUI должен правильно проинструктировать Logic, чтобы он делал то, что ему нужно, и возвращать результаты обратно в GUI.

Несколько других комментариев:

  • Я бы сделал ваш элемент Logic num константой, поскольку он не меняется
  • Если вы никогда не меняете свой объект логики для своего графического интерфейса, нет причин передавать его в конструктор.
  • Если вы хотите изменить свой объект Logic, я бы создал свойство с именем Logic в вашем классе графического интерфейса, чтобы вы могли получить к нему доступ и изменить его при необходимости.
  • Если вы действительно хотите стать модным, вы должны хранить свой уровень доступа к данным (бизнес-логику) в отдельной библиотеке от графического интерфейса пользователя, чтобы его могли использовать все ваши интерфейсы / приложения. Затем вы импортируете свою библиотеку логики в любые интерфейсы, которые в ней нуждаются.
...