簡體   English   中英

我可以使用設計模式來解決這個問題嗎?

[英]Can I use a design pattern to solve this problem?

我正在根據屏幕分辨率向各種 GUI 屏幕添加行間隔。 當前,在各種 GUI 類中,調用了一個方法,該方法返回屏幕分辨率並根據屏幕分辨率添加新的間隔。 根據 class 類型,SpacerField 的值可以更改。 是否有一種設計模式可以用來重構代碼,以減少條件條件,並且更面向 object?

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

    }

在您的第二個示例中,您正在應用委托模式 如果您需要的只是將應用程序組合到模式集合中,那么您就走在了正確的道路上。 但是,如果您想讓您的代碼易於理解,那么最好將間隔寬度檢測委托給 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;
    }
}

然后,稍后在您的 class 中,您有getScreenResolution方法:

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

這可能不是最好的解決方案,但是(就 OO 范式而言)比您第一次和第二次嘗試中建議的要好。

編輯還請注意@eznme 如何回答您的問題。 他的想法可能更適合您的問題。

如果您想要一些易於擴展的東西,例如添加更多具有不同值的類,例如 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;
            }
    }

您只需要一個 class。 類應該在行為而不是數據上有所不同,您甚至不應該根據不同的數據創建兩個不同的類。 這帶來了無用的 class 擴散。 可以在構造函數中提供不同的配置。

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

}

這是配置,使用依賴注入框架創建這些實例並在必要時使用 setters 方法注入實例是一種很好的做法。

即使您不使用依賴注入框架,您現在也可以自己做,將來進行遷移。 方法如下:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM