2011-07-16 3 views
1

Я добавляю строку spacer к различным экранам графического интерфейса в зависимости от разрешения экрана. В настоящее время в различных классах GUI есть призывы к методу, который возвращает разрешение экрана и добавляет новый разделитель в зависимости от разрешения экрана. В зависимости от типа класса значение SpacerField может измениться. Есть ли шаблон проектирования, который я могу использовать для рефакторинга кода, так что есть меньше условных выражений и он ориентирован скорее на объект?Могу ли я использовать шаблон дизайна для решения этой проблемы?

Class A: 
      if(getScreenResolution() == 360){ 
       add(new SpacerField(15)); 
      } 

      if(getScreenResolution() == 460){ 
       add(new SpacerField(5));  
      } 


Class B: 
      if(getScreenResolution() == 360){ 
       add(new SpacerField(35)); 
      } 

      if(getScreenResolution() == 460){ 
       add(new SpacerField(15)); 
      } 

Возможное решение -

add(new SpacerUtils.getSpacerField(this)); 

public static SpacerUtils { 
    static { 
     int screenRes = getScreenRes(); 
    } 

    public static SpacerField getSpacerField(Object obj) { 

     if(obj instanceof GuiScreen1 && screenRes == 360){ 
      return new SpacerField(25); 
     } 
     else if(obj instanceof GuiScreen2 && screenRes == 360){ 
      return new SpacerField(35); 
     } 

    } 
} 

Что-то вроде этого? Для каждого возможного значения проставки мне нужно добавить новую реализацию, в этом случае у меня есть только один - SpacerSmall.

Caller - 
        Spacer spacer = new SpacerSmall(); 

        if(resolution == 360){ 
        add(new SpacerField(0 , spacer.getSpacerValue())); 
        } 


Interface -     
        public interface Spacer { 

     public int getSpacerValue(); 

    } 

Implementation - 
    public class SpacerSmall implements Spacer{ 

     public int getSpacerValue() { 
      return 15; 
     } 

    } 
+7

Вы можете использовать что-нибудь, чтобы решить эту проблему. Вы не должны слепо полагаться на дизайн pattens, чтобы сделать все хорошо для вас. Подумайте сами. – Vlad

+0

Позвольте [менеджеру макетов] (http://download.oracle.com/javase/tutorial/uiswing/layout/visual.html) выполнить эту работу. – trashgod

+0

@ Vlad Хорошо, я добавил возможное решение, что вы думаете? Он содержит много условностей, которые являются плохим шаблоном проектирования? –

ответ

1

Вам нужен только один класс. Классы должны отличаться от поведения не по данным, вы не должны даже создавать два разных класса на основе разных данных. Это приводит к бесполезному распространению класса. В конструкторе может быть предусмотрена другая конфигурация.

public interface Spacer { 

    public SpacerField getSpacer(int resolution); 

} 

public class MySpacer implements Spacer { 

    private Map<Integer, Integer> spacerSize; 

    public MySpacer(Map spacerSize<Integer, Integer>) { 
     this.spacerSize = spacerSize; 
    } 

    public SpacerField getSpacer(int resolution) { 
     Integer size = spacerSize.get(resolution); 
     if (size == null) { 
      throw new IllegalArgumentException("Invalid resolution: " 
          + resolution); 
     } 
     return new SpacerField(size); 
    } 

} 

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

Даже если вы не используете инфраструктуру инъекций зависимостей, вы можете сделать это сейчас и перенести в будущем. Вот как:

public class AClassThatUseSpacer { 

    private Spacer spacer; 

    public void setSpacer(Spacer spacer) { 
     this.spacer = spacer; 
    } 
} 

И когда вы его используете:

AClassThaUseSpacer anInstance = new AClassThatUseSpacer(); 
Map<Integer, Integer> spacerSize = new HashMap<Integer, Integer>(); 
spacerSize.put(360, 15); 
spacerSize.put(460, 5); 
anInstance.setSpacer(new MySpacer(spacerSize)); 
+0

Итак, чтобы получить доступ к Spacer, я могу просто использовать - this.spacer.getSpacer (getResolution) ; ? –

+0

Да, или просто spacer.getSpacer (разрешение); предполагая, что разрешение является переменной, удерживающей ваше текущее разрешение. – stivlo

2

В вашем втором примере вы применяете delegation pattern. Если все, что вам нужно, состоит в том, чтобы скомпоновать ваше приложение в коллекцию паттернов, то вы на правильном пути. Но если вы хотите, чтобы ваш код легко понять, то лучше делегировать обнаружение ширины распорки к объектам классов А и В. Как это, например:

public interface SpacerWidthResolver { 
    public int getSpacerWidth(int resolution); 
} 

public class A implements SpacerWidthResolver { 
    public int getSpacerWidth(int resolution) { 
     int spacerWidth = -1; 
     switch (resolution) { 
      case 360: { 
       spacerWidth = 15; 
       break; 
      } 
      case 460: { 
       spacerWidth = 5; 
       break; 
      } 
      default: { 
       spacerWidth = -1; 
       break; 
      } 
     } 
     return spacerWidth; 
    } 
} 
public class B implements SpacerWidthResolver { 
    public int getSpacerWidth(int resolution) { 
     int spacerWidth = -1; 
     switch (resolution) { 
      case 360: { 
       spacerWidth = 35; 
       break; 
      } 
      case 460: { 
       spacerWidth = 15; 
       break; 
      } 
      default: { 
       spacerWidth = -1; 
       break; 
      } 
     } 
     return spacerWidth; 
    } 
} 

А потом, позже в своем классе, где у вас есть getScreenResolution метод:

public void DoSomething(SpacerWidthResolver component) { 
    add(new SpacerField(component.getSpacerWidth(getScreenResolution()))); 
} 

Это может быть не лучшим решением, но все же лучше (с точки зрения ОО парадигмы), чем предложено в вашей первой и второй попытки.

EDIT Также обратите внимание, как @eznme отвечает на ваш вопрос. Его идея может быть более подходящей для вашей проблемы.

1

Если вы хотите что-то легко расширяемым, как добавить больше классов, как A и B с различными значениями вы можете сделать это:

class Z { 
      abstract int small(); 
      abstract int large(); 
      void doSomething() { 
        if(getScreenResolution() == 360){ 
          add(new SpacerField(this.small())); 
        } 
        if(getScreenResolution() == 460){ 
          add(new SpacerField(this.large));  
        } 
      } 
    } 
    class A extends Z { 
      int small() { 
        return 15; 
      } 
      int large() { 
        return 5; 
      } 
    } 
    class B extends Z { 
      int small() { 
        return 35; 
      } 
      int large() { 
        return 15; 
      } 
    } 
0
class A: 
private static Map<Integer, Integer> spacerMap = new HashMap<Integer, Integer>() {{put(360, 15);put(460, 5);};}; 
... 
add(new SpacerField(spacerMap.get(getScreenResolution()))) 

class B: 
private static Map<Integer, Integer> spacerMap = new HashMap<Integer, Integer>() {{put(360, 35);put(460, 15);};}; 
... 
add(new SpacerField(spacerMap.get(getScreenResolution()))) 
Смежные вопросы