我根据屏幕分辨率在各种GUI屏幕上添加了一个行间隔符。目前在各种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;
}
}
答案 0 :(得分:2)
在您的第二个示例中,您正在应用delegation pattern。如果你需要的是将你的应用程序组合成模式集合,那么你就是正确的方式。但是如果你想让你的代码易于理解,那么最好将间隔宽度检测委托给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())));
}
这可能不是最好的解决方案,但是在你的第一次和第二次尝试中建议的更好(就OO范式而言)。
编辑另请注意@eznme如何回答您的问题。他的想法可能更适合你的问题。
答案 1 :(得分: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;
}
}
答案 2 :(得分: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);
}
}
这是配置,使用依赖注入框架创建这些实例并使用setter方法在必要时注入实例是一种很好的做法。
即使你不使用依赖注入框架,你现在可以自己做,并在将来进行迁移。方法如下:
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));
答案 3 :(得分: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())))