做的一个比较老的系统,不要吐槽别人的代码烂 发现不足并改变就是进步
代码中有很多if else的代码 可读性很差 在想怎么能进行优化在,找到并学习了策略模式的使用
if (msgType = "文本") {
// dosomething
} else if(msgType = "图片") {
// doshomething
} else if(msgType = "视频") {
// doshomething
} else {
// doshomething
}
如图以下的代码 如果条件很多就会变得很夸张很难读 现在将以下的代码进行优化
1、定义枚举类
public enum MSG_TYPE {
TEXT(1, "文本"),
IMAGE(2, "图片"),
VIDEO(3, "视频");
public final int code;
public final String name;
MSG_TYPE(int code, String name) {
this.code = code;
this.name = name;
}
}
2、定义一个注解
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MsgTypeHandler {
MSG_TYPE value();
}
3、策略处理的接口
public interface MessageService {
void handleMessage(MessageInfo messageInfo);
}
4、接口的实现类
@Service
@MsgTypeHandler(value = MSG_TYPE.TEXT)
public class TextMessageService implements MessageService {
@Override
public void handleMessage(MessageInfo messageInfo) {
System.out.println("处理文本消息 " + messageInfo.getContent());
}
}
@Service
@MsgTypeHandler(value = MSG_TYPE.IMAGE)
public class ImageMessageService implements MessageService {
@Override
public void handleMessage(MessageInfo messageInfo) {
System.out.println("处理图片消息 " + messageInfo.getContent());
}
}
在spring启动的时候将类型和service实现以map的形式储存到Context中
@Component
public class MessageServiceContext {
private final Map<Integer, MessageService> handlerMap = new HashMap<>();
public MessageService getMessageService(Integer type) {
return handlerMap.get(type);
}
public void putMessageService(Integer code, MessageService messageService) {
handlerMap.put(code, messageService);
}
}
@Component
public class MessageServiceListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
Map<String, Object> beans = event.getApplicationContext().getBeansWithAnnotation(MsgTypeHandler.class);
MessageServiceContext messageServiceContext = event.getApplicationContext().getBean(MessageServiceContext.class);
beans.forEach((name, bean) -> {
MsgTypeHandler typeHandler = bean.getClass().getAnnotation(MsgTypeHandler.class);
messageServiceContext.putMessageService(typeHandler.value().code, (MessageService) bean);
});
}
}
现在说一下什么是策略模式
策略模式(Strategy),定义了一组算法,将每个算法都封装起来,并且使它们之间可以互换。UML结构图如下:
其中,Context是上下文,用一个ConcreteStrategy来配置,维护一个对Strategy对象的引用;Strategy是策略类,用于定义所有支持算法的公共接口;ConcreteStrategy是具体策略类,封装了具体的算法或行为,继承于Strategy。
以及网上的一个栗子
1. 上下文类
首先声明一个CashSuper对象,通过构造方法,传入具体的收费策略,getResult()方法的功能为根据收费策略的不同获得计算结果。
public class CashContext {
private CashSuper cashSuper;
public CashContext(CashSuper cashSuper) {
this.cashSuper = cashSuper;
}
public double getResult(double money) {
return cashSuper.acceptCash(money);
}
}
2. 现金收费抽象类
策略类,为抽象类,抽象出收费的方法供子类实现。
public abstract class CashSuper {
public abstract double acceptCash(double money);
}
3. 正常收费子类
没有任何活动的情况,正常收费,返回原价。
public class CashNormal extends CashSuper {
@Override
public double acceptCash(double money) {
return money;
}
}
4. 打折收费子类
打折活动,根据折扣返回打折后的价格。
public class CashRebate extends CashSuper {
private double moneyRebate = 1; //折扣
public CashRebate(double moneyRebate) {
this.moneyRebate = moneyRebate;
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
5. 返利收费子类
public class CashReturn extends CashSuper {
private double moneyConditation = 0.0; //返利条件
private double moneyReturn = 0.0d; //返利值
public CashReturn(double moneyConditation, double moneyReturn) {
this.moneyConditation = moneyConditation;
this.moneyReturn = moneyReturn;
}
@Override
public double acceptCash(double money) {
double result = money;
if (money >= moneyConditation) {
result = money - Math.floor(money / moneyConditation) * moneyReturn;
}
return result;
}
}
6. Client客户端
public class Client {
public static void main(String[] args) {
CashContext cashContext = null;
Scanner scanner = new Scanner(System.in);
System.out.print("请输入打折方式(1/2/3):");
int in = scanner.nextInt();
String type = "";
switch (in) {
case 1:
cashContext = new CashContext(new CashNormal());
type += "正常收费";
break;
case 2:
cashContext = new CashContext(new CashReturn(300, 100));
type += "满300返100";
break;
case 3:
cashContext = new CashContext(new CashRebate(0.8));
type += "打8折";
break;
default:
System.out.println("请输入1/2/3");
break;
}
double totalPrices = 0;
System.out.print("请输入单价:");
double price = scanner.nextDouble();
System.out.print("请输入数量:");
double num = scanner.nextDouble();
totalPrices = cashContext.getResult(price * num);
System.out.println("单价:" + price + ",数量:" + num + ",类型:" + type + ",合计:" + totalPrices);
scanner.close();
}
}
正常收费结果如下:
返利收费结果如下:
打折收费结果如下: