java策略模式+工厂模式+模板模式

32 篇文章 0 订阅
20 篇文章 0 订阅
本文探讨如何利用策略模式、工厂模式和模板模式优化代码,避免if...else...,提升代码灵活性与扩展性。通过实例展示了如何创建策略接口、策略实现类和统一工厂,以及如何通过模板模式简化策略接口的维护。
摘要由CSDN通过智能技术生成

策略模式+工厂模式+模板模式彻底取代 if...else...

策略模式:一种解耦的方法,它对算法进行封装,使得算法的调用和算法本身分离。使用策略模式客户端代码不需要调整,算法之间可以互相替换,因为不同的算法实现的是同一个接口。策略模式是一种对象行为型模式。策略模式符合“开闭原则”。

策略模式包括如下角色:

  • Context :环境类

  • Strategy:抽象策略类

  • ConcreteStrategy:具体策略类

代码实现:

枚举类:

public enum SubCostTypeEnum {

    GREATER0_IN_0UP(7, "原始>0,入库后>0"),
    EQUAL0_OUT_0DOWN(8, "原始=0,出库后<0"),

    ;

    private Integer value;
    private String description;

    private SubCostTypeEnum(Integer value, String description) {
        this.value = value;
        this.description = description;
    }

    public Integer value() {
        return value;
    }

    public String description() {
        return description;
    }

    public static SubCostTypeEnum valueOf(Integer value) {
        for(SubCostTypeEnum type : SubCostTypeEnum.values()) {
            //if(type.value() == value) {
            if(type.value().equals(value)) {
                return type;
            }
        }
        return null;
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class KcBook {
    private BigDecimal beforeQty;
    private BigDecimal beforeAmount;
    private Integer direction;
    private BigDecimal qty;
    private BigDecimal price;
    private BigDecimal afterQty;
    private BigDecimal afterAmount;
}

定义策略接口:

org.springframework.beans.factory.InitializingBean#afterPropertiesSet内部实现工厂注册。用于实现环境的统一工厂。

public interface RechargeHandler extends InitializingBean {
    public BigDecimal getAvgPrice(KcBook kcBook) {
        System.out.println("getAvgPrice");
        return new BigDecimal("0");
    }

    public void getRechargeName(SubCostTypeEnum subCostType) {
        System.out.println("默认: " + subCostType);
    }
}

实现策略工厂:

public class StrategyHandlerFactory {
    private static Map<SubCostTypeEnum, CostHandler> strategyMap = new ConcurrentHashMap<>();

    /**
     * 根据 SubCostTypeEnum 获取对应的handler实现
     *
     * @param subCostType
     * @return
     */
    public static CostHandler getInvokeStrategyMap(SubCostTypeEnum subCostType) {
        return strategyMap.get(subCostType);
    }

    /**
     * 注册
     *
     * @param subCostType
     * @param handler
     */
    public static void register(SubCostTypeEnum subCostType, CostHandler handler) {
        if (null == subCostType || null == handler) {
            return;
        }
        strategyMap.put(subCostType, handler);
    }
}

各成员实现各自的策略实现类:

@Component
public class SubCost1Handler implements CostHandler {
    @Override
    public void getRechargeName(SubCostTypeEnum subCostType) {
        System.out.println("1: " + subCostType);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyHandlerFactory.register(SubCostTypeEnum.GREATER0_IN_0UP, this);
    }

    @Override
    public BigDecimal getAvgPrice(KcBook kcBook) {
        System.out.println("getAvgPrice");
        BigDecimal tmp = kcBook.getBeforeAmount().add(kcBook.getQty().multiply(kcBook.getPrice())).divide(kcBook.getBeforeQty().add(kcBook.getQty()), 2, BigDecimal.ROUND_HALF_UP);
        System.out.println("getAvgPrice:" + tmp) ;
        return tmp;
    }
}

如有其它新类型业务,值需要实现对应的策略即可。

test

    @Test
    public void test01(){
        SubCostTypeEnum subCostType = null;
        CostHandler costHandler = null;

        subCostType = SubCostTypeEnum.GREATER0_IN_0UP;
        costHandler = StrategyHandlerFactory.getInvokeStrategyMap(costType, subCostType);
        System.out.println(costHandler);
        KcBook kcBook = new KcBook(new BigDecimal("100"), new BigDecimal("150"), 1, new BigDecimal("2"), new BigDecimal("20"), new BigDecimal("120"), new BigDecimal("190"));
        BigDecimal avg = costHandler.getAvgPrice(kcBook);
        System.out.println(avg);
    }

使用模板模式改造策略模式接口:

上述实现,若策略接口新增了方法,那么所有实现了改策略接口的实现类都要进行修改,对现有已完成的类改动较大,使用先将其改为模板模式。

将原有接口改造为抽象类

public abstract class CostHandler implements InitializingBean {
    public void getRechargeName(SubCostTypeEnum subCostType) {
        System.out.println("默认: " + subCostType);
    }

    public BigDecimal getAvgPrice(KcBook kcBook) {
        System.out.println("getAvgPrice");
        return new BigDecimal("0");
    }
}

子类重新继承改抽象类即可

@Component
public class SubCost1Handler extends CostHandler {
    @Override
    public void getRechargeName(SubCostTypeEnum subCostType) {
        System.out.println("1: " + subCostType);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyHandlerFactory.register(SubCostTypeEnum.GREATER0_IN_0UP, this);
    }

    @Override
    public BigDecimal getAvgPrice(KcBook kcBook) {
        System.out.println("getAvgPrice");
        BigDecimal tmp = kcBook.getBeforeAmount().add(kcBook.getQty().multiply(kcBook.getPrice())).divide(kcBook.getBeforeQty().add(kcBook.getQty()), 2, BigDecimal.ROUND_HALF_UP);
        System.out.println("getAvgPrice:" + tmp) ;
        return tmp;
    }
}

这样,抽象类中增加了新的方法后,已有的子类在不需要新增方法时,可以不用调整。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值