Могу ли я использовать шаблон проектирования для решения этой проблемы? - PullRequest
1 голос
/ 16 июля 2011

Я добавляю проставки строк к различным экранам графического интерфейса в зависимости от разрешения экрана. В настоящее время в различных классах 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);
        }

    }
}

Как то так? Для каждого возможного значения spacer мне нужно добавить новую реализацию, в данном случае у меня есть только одна - 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;
        }

    }

Ответы [ 4 ]

2 голосов
/ 16 июля 2011

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

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())));
}

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

РЕДАКТИРОВАТЬ Также обратите внимание, как @eznme отвечает на ваш вопрос.Его идея может быть более подходящей для вашей проблемы.

1 голос
/ 16 июля 2011

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

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));
1 голос
/ 16 июля 2011

Если вы хотите что-то легко расширяемое, например, добавив больше классов, таких как 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 голосов
/ 16 июля 2011
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())))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...