«Если» заявление против ОО Дизайн - 2 - PullRequest
0 голосов
/ 21 декабря 2010

Я сталкивался с подобной проблемой оператор "if" против OO Design - 1 , но он немного отличается. Вот проблема, которая открывает всплывающее окно (различные объекты / всплывающие окна) по значению изменения списка

Popup1 p1; // different objects
Popup2 p2; // different objects
Popup3 p3;
...

listbox.add("p1");
listbox.add("p2");
listbox.add("p3");
...

listbox.addChangeHandler() {
    if(getSelectedItem().equals("p1")){
       p1 = new Popup1();
       p1.show();
    } else if() {...}
      ....
}

Я не хочу писать «если», что если p1, то p1 = new Popup1(); p1.center();

Как я могу справиться с этой ситуацией? Любой дизайн-шаблон?

Вот мое решение, но оно очень дорогое

map() {

    map.put("p1", new Popup1());
    map.put("p2", new Popup2());
    map.put("p3", new Popup3()); 
}

onValueChange() {
    map.get(selectedItem).show();
}

Один недостаток - инициализация всех всплывающих окон. но это требуется только когда valueChange

Ответы [ 6 ]

1 голос
/ 21 декабря 2010

Хорошо, если P1 и P2 оба реализуют один и тот же интерфейс, т.е.

Popup1 implements Showable
Popup2 implements Showable

тогда вы могли бы просто сделать

Showable showable = (Showable) listbox.getSelected();
showable.show();
0 голосов
/ 21 декабря 2010

К сожалению, нет никакого способа обойти то, что вы упомянули с учетом ограничений.

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

В противном случае, лучшее, что вы можете сделать, это инкапсулировать его в фабричный класс, такой как @JST, упомянутый, таким образом, уродливая логика существует только в одном месте.Я не уверен, почему вы считаете ваше решение map дорогостоящим.

Если вы хотите динамически вызывать конструктор на основе имени, вам придется смотреть на динамический язык вместо Java.

0 голосов
/ 21 декабря 2010

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

for (String key: map.keyset())
    listbox.add(key);

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

ArrayList<String> list = new ArrayList<String>();
list.addAll(map.keySet());
Collections.sort(list);
for (String key: list)
    listbox.add(key);
0 голосов
/ 21 декабря 2010

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

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

Один недостаток - инициализация всех всплывающих окон. но это требуется только когда valueChange

Вы должны отложить создание экземпляра до тех пор, пока оно вам не понадобится:

interface Showable {
    void show();
}
map() {

    map.put("p1", new Showable() { void show() { new Popup1().show(); } } );
    map.put("p2", new Showable() { void show() { new Popup2().show(); } } );
    map.put("p3", new Showable() { void show() { new Popup3().show(); } } ); 
}

onValueChange() {
    map.get(selectedItem).show();
}

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

0 голосов
/ 21 декабря 2010

Если на самом деле существует три разных класса Popup1, Popup2, Popup3, то они должны либо наследовать от общего базового класса (предположительно называемого Popup), либо реализовать общий интерфейс (как уже предлагалось).Но, похоже, вам нужен способ сопоставления строк, идентифицирующих всплывающие окна, с всплывающими объектами.Звучит как возможность для фабричного шаблона, который будет выглядеть примерно так.

public class PopupFactory {
   private PopupFactory() { }
   public static Popup createPopup(String popupIdentifier) {
      if ("p1".equals(popupIdentifier)) return new Popup1();
      else if ("p2".equals(popupIdentifier)) return new Popup2();
      ...
   }

А затем будет использоваться как:

listbox.addChangeHandler() {
   Popup popup = PopupFactory.createPopup(getSelectedItem());
   popup.show();
   ....
}
0 голосов
/ 21 декабря 2010

Да, этот шаблон дизайна называется полиморфизмом.Вы определяете суперкласс для всех ваших классов PopupX.В этом суперклассе вы определяете метод "onChange".Затем вы реализуете этот метод в каждом подклассе.Когда вы выбираете элемент, вы определяете ссылку на объект суперкласса и вызываете «onChange».

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