重构之重复代码: 1.(重复代码是)语义一致的逻辑
反例:语义一致的逻辑产生了多个实体
缺点:如果你为语义一致的逻辑产生了多个实体,那么当需要修改这个逻辑时,你必须保证同时修改所有的实体,并确保它们是一致的。否则,程序就会产生bug。无疑,这么做会额外增加很多的不必要的工作量。 原则:语义一致的逻辑之应该只产生唯一实体,在需要的地方进行调用。 反面案例:
jdbc操作数据库时,在每个访问方法中写driverClass, url, username, password。 2.(重复代码是)非语义一致的逻辑。
当你的程序中存在多个实体,表示的是非语义一致的逻辑,当修改其中一个不需要维护另一个,因为它们本身就没有语义一致的要求。 重构之switch语句: 程序中出现switch语句,就是不好的设计吗? 一个需要重构的switch语句的案例
Movie类
priceCode域
getCharge(int daysRent):
存在switch语句:
根据priceCode域的值的不同计算租片费用。
其中每个分支中的逻辑的共同点:
输入是租期,输出是费用。 方案:
使用状态模式或策略模式对该switch语句进行重构。 商城案例:根据会员不同的等级,给与不同的折扣,会员等级是变化点
会员等级,折扣计算。
影片案例:根据影片类型,计算积分和费用(租用时间),影片类型是变化点
影片类型,计算积分,计算费用。 静态的方法:
charge getCharge(movieType, daysRent){
switch(movieType)
case x1: xx
case x2: xx
case x3: xx
} points getPoints(movieType, daysRent){
switch(movieType)
case x1: xx
case x2: xx
case x3: xx
}
类型作为条件,影响方法的行为。 满减
amount getAmount(amount, customerType){
amount > x1
xxx
amount > x2
xxx
amount > x3
xxx switch(customerType)
case x1: xx
case x2: xx
case x3: xx
}
金额作为条件,影响方法的行为。
会员类型作为条件,影响方法的行为。 满减+打折(大话设计模式中案例) amount getAmount(code, amount){
switch(code)
case 打折x1: xx
case 打折x2: xx
case 满减x1: xx
case 满减x2: xx
} amount getAmount(amount){
switch(code)
case 打折x1: cashRebate(折扣)
case 打折x2: cashRebate(折扣)
case 满减x1: cashReturn(满, 减)
case 满减x2: cashReturn(满, 减)
}
cashRebate(折扣);
cashReturn(满, 减);//考虑,满减可能有多对,这时可以用一个数组来表示。 //可能的过度设计,使用策略模式
CashSuper, CashRebate, CashReturn acceptCash() Rental中保存daysRent信息,Movie中保存type信息 程序中有个元素,该元素有限个值,程序中受该元素的值影响的行为。
元素是影片类型,并且该影片类型作为条件影响程序的行为是计算费用和计算积分。 例如,如下场景,switch case分支语句过多: /**
* 获取地市编码对应的地市名称
*
* @param cityId 地市编码
* @return String 地市名称
*/
public static String getCityName(int cityId) {
switch (cityId) {
//苏州
case GlobalDefine.DATUM_CITY_ID_SZ: {
return "sz";
}
//淮安
case GlobalDefine.DATUM_CITY_ID_HA: {
return "hz";
}
//宿迁
case GlobalDefine.DATUM_CITY_ID_SQ: {
return "sq";
}
//南京
case GlobalDefine.DATUM_CITY_ID_NJ: {
return "nj";
}
//连云港
case GlobalDefine.DATUM_CITY_ID_LYG: {
return "lyg";
}
//徐州
case GlobalDefine.DATUM_CITY_ID_XZ: {
return "xz";
}
//常州
case GlobalDefine.DATUM_CITY_ID_CZ: {
return "cz";
}
//镇江
case GlobalDefine.DATUM_CITY_ID_ZJ: {
return "zj";
}
//无锡
case GlobalDefine.DATUM_CITY_ID_WX: {
return "wx";
}
//南通
case GlobalDefine.DATUM_CITY_ID_NT: {
return "nt";
}
//泰州
case GlobalDefine.DATUM_CITY_ID_TZ: {
return "tz";
}
//盐城
case GlobalDefine.DATUM_CITY_ID_YC: {
return "yc";
}
//扬州
case GlobalDefine.DATUM_CITY_ID_YZ: {
return "yz";
}
//所有地市
case GlobalDefine.DATUM_CITY_ALL: {
return "all";
}
default:
return "";
} 使用HashMap来解决switch case 分支语句过多的情况 /**
* 获取地市编码对应的地市名称
*
* @param cityId 地市编码
* @return String 地市名称
*/
public static String getCityName(int cityId) { Map<Short, String> cityMap = new HashMap<Short, String>();
//苏州
cityMap.put(GlobalDefine.DATUM_CITY_ID_SZ, "sz"); //淮安
cityMap.put(GlobalDefine.DATUM_CITY_ID_HA, "ha"); //宿迁
cityMap.put(GlobalDefine.DATUM_CITY_ID_SQ, "sq"); //南京
cityMap.put(GlobalDefine.DATUM_CITY_ID_NJ, "nj"); //连云港
cityMap.put(GlobalDefine.DATUM_CITY_ID_LYG, "lyg"); //徐州
cityMap.put(GlobalDefine.DATUM_CITY_ID_XZ, "xz"); //常州
cityMap.put(GlobalDefine.DATUM_CITY_ID_CZ, "cz"); //镇江
cityMap.put(GlobalDefine.DATUM_CITY_ID_ZJ, "zj"); //无锡
cityMap.put(GlobalDefine.DATUM_CITY_ID_WX, "wx"); //南通
cityMap.put(GlobalDefine.DATUM_CITY_ID_NT, "nt"); //泰州
cityMap.put(GlobalDefine.DATUM_CITY_ID_TZ, "tz"); //盐城
cityMap.put(GlobalDefine.DATUM_CITY_ID_YC, "yc"); //扬州
cityMap.put(GlobalDefine.DATUM_CITY_ID_YZ, "yz"); //所有地市
cityMap.put(GlobalDefine.DATUM_CITY_ALL, "all"); if (cityMap.containsKey((short) cityId)) {
return cityMap.get((short) cityId);
} else {
return "cityId is error and not find this cityName by cityId";
} public static int getServiceCode(String str){
int code = 0;
if(str.equals("Age")){
code = 1;
}else if(str.equals("Address")){
code = 2;
}else if(str.equals("Name")){
code = 3;
}else if(str.equals("No")){
code = 4;
}
return code;
} public static void initialMap(){
map.put("Age",1);
map.put("Address",2);
map.put("Name",3);
map.put("No",4);
}
收集的switch语句