用策略模式重构很多if else的代码

做的一个比较老的系统,不要吐槽别人的代码烂 发现不足并改变就是进步
代码中有很多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结构图如下:

image

其中,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();
    }

}

正常收费结果如下:

image

返利收费结果如下:

image

打折收费结果如下:

image
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容