如何用模式代替if else

xiaotangtang2 2010-08-05 12:14:01
面向过程的开发中代码有大量的IF ELSE.想通过一些设计模式替换掉这些逻辑。在网上找了一些资料,大多是说用多态或者策略模式实现。但我觉得还是没搞明白。比如说,从数据库里取出了一条记录person,如果是性别是1,就打印出“男人”,是2,就打印出“女人”,怎么实现呢?如果客户端明白自己要用何种策略,当然可以用策略模式,但这种依赖于数据自身的判断,如果能从根本上避免if else呢?
...全文
1556 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
ronniegxq 2010-08-06
  • 打赏
  • 举报
回复
在常量里定义一个map 把1 -男,2-女put进去,在页面上直接调用getMap()把参数传进去,就自动取出男还是女了。
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 xiaotangtang2 的回复:]

在这里我想问大家,在实际的开发中应该有很多基于数据库中某个字段的逻辑判断,然后调用不同的方法。我以前都是用IF ELSE,确实不好维护,你们都是用什么好方法的呢?

除了用配置文件加上反射,到底还有没有更高明的办法?这个问题应该是非常非常非常常见的,希望各位能够给我指点迷津。
[/Quote]

如果字段的值是不定的,以后可能会增加,要这样的话,恕我能力有限,想不出什么更高明的办法了。
xiaotangtang2 2010-08-06
  • 打赏
  • 举报
回复
在这里我想问大家,在实际的开发中应该有很多基于数据库中某个字段的逻辑判断,然后调用不同的方法。我以前都是用IF ELSE,确实不好维护,你们都是用什么好方法的呢?

除了用配置文件加上反射,到底还有没有更高明的办法?这个问题应该是非常非常非常常见的,希望各位能够给我指点迷津。
welllit 2010-08-06
  • 打赏
  • 举报
回复
在常量里定义一个map 把1 -男,2-女put进去,在页面上直接调用getMap()把参数传进去,就自动取出男还是女了。
xiaotangtang2 2010-08-06
  • 打赏
  • 举报
回复
状态模式。
http://www.blogjava.net/xzclog/archive/2006/10/16/75399.html
---------------------------------------------------------------------
状态模式的方法也有人提过了,但最终还是用了反射,而且类型是写在代码中的,应该没有用配置文件进行反射的效果好。
xiaotangtang2 2010-08-06
  • 打赏
  • 举报
回复
15楼的哥们可能还不太清楚我的意思。我知道用多态是可以区分的,但关键是你不知道在代码中用多态的哪个实现类呀
xiaotangtang2 2010-08-06
  • 打赏
  • 举报
回复
多谢13楼的兄弟,从目前来看,也就是这一个方法了,多谢了
huguang 2010-08-05
  • 打赏
  • 举报
回复
关于大量if else的问题,可以看看chain of responsibility和state等模式,用户性别这个好像没必要搞那么复杂了。
yumyy 2010-08-05
  • 打赏
  • 举报
回复
状态模式。
http://www.blogjava.net/xzclog/archive/2006/10/16/75399.html
bastengao 2010-08-05
  • 打赏
  • 举报
回复

abstract class Person{

abstract String getGender();

}

class Femal extends Person{

String getGender(){
return "femal";
}
}



class Male extends Person{

String getGender(){
return "male";
}
}


  • 打赏
  • 举报
回复
上面代码至于为什么我会在构造中检查配置的类型,那是由于就算使用者不小心配错了,那么在加载配制文件时就能抛出异常,而不需要等到用到这个类时再抛出来,那样的话就太危险了。
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 xiaotangtang2 的回复:]

这本书我看过,但并不能解决现在的问题。多态和策略是在客户端知道自己需要一个什么样的实现类的时候,自己实例话一个。但现在你要根据数据的具体情况判断,我不知道怎么实现呀。可以看下重构中MOVIE的代码,重构后有一段时这样的:
public void setPriceCode(int arg) { // <-- changed
switch (arg) {
……
[/Quote]

Martin Folwer 在《重构》一书中只是简化了一下,因为这本书也不是讲授面向对象设计的,所以也没有讲到如何使用代码更具有“开-闭原则”。要把这里面的 switch 消除掉,改为一个真正意义上可扩展的面向对象代码需要进行代码结构上的改动。

1:创建一个配置 price code 与具体实现类对应的 XML 配置文件,这个 XML 片段假设如下:

<prices>
<price code="1" classname="com.test.RegularPrice" />
<price code="2" classname="com.test.ChildrensPrice" />
<price code="3" classname="com.test.NewReleasePrice" />
</prices>


2:创建一个对应于 price 的映射类,便于管理 Price 的实现。注意这个类的构造访问范围应限制在当前包中,解析 XML 的类也应在该包中。

import java.util.HashMap;
import java.util.Map;

public class PriceConfig {

private int code;
private Class<Price> clazz;
private static Map<Integer, PriceConfig> map = new HashMap<Integer, PriceConfig>();

PriceConfig(int code, String classname) {
this.code = code;
this.clazz = initClass(classname);
register(this);
}

@SuppressWarnings("unchecked")
private Class<Price> initClass(String classname) {
Class<Price> clazz = null;
try {
clazz = (Class<Price>)Class.forName(classname);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(classname + " isnot exist");
}
if(!clazz.isAssignableFrom(Price.class)) {
throw new IllegalArgumentException(classname + " isnot Price implementation");
}
return clazz;
}

private static void register(PriceConfig priceConfig) {
map.put(priceConfig.getCode(), priceConfig);
}

public static Price getPrice(int code) {
PriceConfig price = map.get(code);
if(price == null) {
new IllegalArgumentException("Incorrect Price Code");
}
return price.getPrice();
}

public int getCode() {
return code;
}

public Class<Price> getClassname() {
return clazz;
}

public Price getPrice() {
try {
return (Price)clazz.newInstance();
} catch (InstantiationException e) {
throw new Xxxxxxxxx();
} catch (IllegalAccessException e) {
throw new Xxxxxxxxx();
}
}
}


3:以后代码直接这样就可以用了:

Price price = PriceConfig.getPrice(CHILDRENS);

经过这样的改造之后就是一个符合“开-闭原则”的易扩展、低耦合的功能了,呵呵。


qianyecq 2010-08-05
  • 打赏
  • 举报
回复
http://www.javaeye.com/topic/26455
工厂模式这里有,不知道合不合用。
xiaotangtang2 2010-08-05
  • 打赏
  • 举报
回复
重构里面很详细的说明了这个问题,使用策略模式
http://haobinbin.javaeye.com/blog/553666
这里有一个使用状态模式的
http://blog.csdn.net/sanshiqiduer/archive/2009/10/26/4730386.aspx

---------------------------------------------
第一个例子,可以看下他实现策略的过程:
public class NoIfElse {
public static void main(String args[]){
MyPaper myPaper = new MyPaper(new White());
myPaper.choicePen();
}
}
他已经明确说了,要一个new White()),现在的问题就是不知道是要一个new White(),还是一个new Blue()


第二个例子我也看了,他是把类型写在了文件里,然后用反射初始化,但这样也不能做到开闭
// 普通片标识
public static String REGULAR = " com.qujingbo.movie.RegularlPrice " ;

// 新片标识
public static String NEW_RELEASE = " com.qujingbo.movie.NewReleasePrice " ;

// 儿童片标识
public static String CHILDREN = " com.qujingbo.movie.ChildrenPrice " ;

bunrise 2010-08-05
  • 打赏
  • 举报
回复
你上面的代码完全可以吧他们放在一个集合里,如hashmap
然后写一个枚举
通过枚举获取不同的实例
bunrise 2010-08-05
  • 打赏
  • 举报
回复
重构里面很详细的说明了这个问题,使用策略模式
http://haobinbin.javaeye.com/blog/553666
这里有一个使用状态模式的
http://blog.csdn.net/sanshiqiduer/archive/2009/10/26/4730386.aspx

程序方面灵活性很多,设计模式懂了,这些在不同场合会得心应手

我用枚举+回调也做过
xiaotangtang2 2010-08-05
  • 打赏
  • 举报
回复
这本书我看过,但并不能解决现在的问题。多态和策略是在客户端知道自己需要一个什么样的实现类的时候,自己实例话一个。但现在你要根据数据的具体情况判断,我不知道怎么实现呀。可以看下重构中MOVIE的代码,重构后有一段时这样的:
public void setPriceCode(int arg) { // <-- changed
switch (arg) {
case REGULAR:
_price = new RegularPrice();
break;
case CHILDRENS:
_price = new ChildrensPrice();
break;
case NEW_RELEASE:
_price = new NewReleasePrice();
break;
default:
throw new IllegalArgumentException("Incorrect Price Code");
}
}
他确实是采用了策略模式,但策略还是在CASE里边呀。
  • 打赏
  • 举报
回复
使用多态。《重构》一书上有讲到这个问题。

if...else, swith...case 是面向过程的代码,在面向对象的代码中应尽可能少地出现。
xiaotangtang2 2010-08-05
  • 打赏
  • 举报
回复
这个问题我想了好几天呀,还是没有结果。有没有高人救我于水火之中呀?
xiaotangtang2 2010-08-05
  • 打赏
  • 举报
回复
大家不要光说呀,给个伪代码也可以呀
加载更多回复(3)

50,528

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧