欧博亚洲电脑版下载:运用设计模式告辞项目中大量臃肿的if else

admin 3个月前 (07-03) 科技 40 0

前言

以前写过的一个老项目中,有这样一个营业场景,比喻:一个外卖系统需要接入多家餐馆,在外卖系统中返回每个餐馆的菜单列表 ,每个餐馆的菜单价钱都需要差别的算法盘算。

代码中使用了大量的if else嵌套毗邻,一个类中数千行代码(眼睛快看瞎...),而且随着营业的扩展,接入的餐馆会越来越多,每接入一个餐馆都要增添一个 if else,满屏幕密密麻麻的逻辑代码,毫无可读性。然后前段时间进行了代码重构,使用了计谋模式+工厂模式+反射取代了这整片的臃肿代码,瞬间神清气爽。

 

模拟原营业代码

原代码的简朴模拟实现,凭据传入的差别餐馆编码获取对应的餐馆类聚集,每个餐馆菜单价钱的算法都差别。每当需要新接入一家餐馆时,都需要在此增添一个if else,中心加入一大长串的处置逻辑,当餐馆越来越多的时刻,代码就变得越来越繁重,维护成本高。

public List server(String hotelCode) {
    if ("HotelA".equals(hotelCode)) {
        //获取数据
        List<HotelA> hotelList = new ArrayList<HotelA>() {
            {
                add(new HotelA("爆炒腰子", 100d, 0.8, null));
                add(new HotelA("红烧腰子", 200d, 0.8, null));
                add(new HotelA("腰子刺身", 300d, 0.8, null));
            }
        };
        //逻辑盘算 最终价钱 = 原价 * 折扣
        hotelList.parallelStream().forEach(v -> v.setFinalPrice(v.getPrice() * v.getDiscount()));
        return hotelList;

    } else if ("HotelB".equals(hotelCode)) {
        //获取数据
        List<HotelB> hotelList = new ArrayList<HotelB>() {
            {
                add(new HotelB("兰州拉面", 100d, 10d, null));
                add(new HotelB("崎岖潦倒后端在线炒粉", 200d, 20d, null));
            }
        };
        //逻辑盘算 最终价钱 = 原价 - 优惠
        hotelList.parallelStream().forEach(v -> v.setFinalPrice(v.getPrice() - v.getPreferential()));
        return hotelList;

    } else if ("HotelC".equals(hotelCode)) {
        //获取数据
        List<HotelC> hotelList = new ArrayList<HotelC>() {
            {
                add(new HotelC("秘制奥利给", 1000d, 0.6, 20d, null));
                add(new HotelC("老八辣酱", 2000d, 0.6, 10d, null));
            }
        };
        //逻辑盘算 最终价钱 = 原价 * 折扣 - 服务
        hotelList.parallelStream().forEach(v -> v.setFinalPrice(v.getPrice() * v.getDiscount() - v.getTip()));
        return hotelList;
    }
    return new ArrayList();
}

 

@Data
@NoArgsConstructor
@AllArgsConstructor
public class HotelA {

    //菜品名
    private String menu;

    //原价
    private Double price;

    //折扣
    private Double discount;

    //最终价钱 = 原价 * 折扣
    private Double finalPrice;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class HotelB {

    //菜品名
    private String menu;

    //原价
    private Double price;

    //优惠
    private Double preferential;

    //最终价钱 = 原价 - 优惠
    private Double finalPrice;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class HotelC {

    //菜品名
    private String menu;

    //原价
    private Double price;

    //折扣
    private Double discount;

    //服务费
    private Double tip;

    //最终价钱 = 原价 * 折扣 - 服务费
    private Double finalPrice;
}

 

计谋模式+工厂模式+反射

由上述代码首先抽离出一个接口,if else中的营业逻辑最终都是返回一个列表

/**
 * 餐馆服务接口
 */
public interface HotelService {

    /**
     * 获取餐馆菜单列表
     * @return
     */
    List getMenuList();
}

 

 

把每个分支的营业逻辑封装成实现类,实现HotelService接口

public class HotelAServiceImpl implements HotelService {

    /**
     * 逻辑盘算 返回聚集
     * @return
     */
    @Override
    public List getMenuList() {
        return initList().parallelStream()
                .peek(v -> v.setFinalPrice(v.getPrice() * v.getDiscount()))
                .collect(Collectors.toList());
    }

    /**
     * 获取数据
     * @return
     */
    public List<HotelA> initList() {
        return new ArrayList<HotelA>() {
            {
                add(new HotelA("爆炒腰子", 100d, 0.8, null));
                add(new HotelA("红烧腰子", 200d, 0.8, null));
                add(new HotelA("腰子刺身", 300d, 0.8, null));
            }
        };
    }
}
public class HotelBServiceImpl implements HotelService {

    /**
     * 逻辑盘算 返回聚集
     * @return
     */
    @Override
    public List getMenuList() {
        return initList().parallelStream()
                .peek(v -> v.setFinalPrice(v.getPrice() - v.getPreferential()))
                .collect(Collectors.toList());
    }

    /**
     * 获取数据
     * @return
     */
    public List<HotelB> initList() {
        return new ArrayList<HotelB>() {
            {
                add(new HotelB("兰州拉面", 100d, 10d, null));
                add(new HotelB("崎岖潦倒后端在线炒粉", 200d, 20d, null));
            }
        };
    }
}
public class HotelCServiceImpl implements HotelService {

    /**
     * 逻辑盘算 返回聚集
     * @return
     */
    @Override
    public List getMenuList() {
        return initList().parallelStream()
                .peek(v -> v.setFinalPrice(v.getPrice() * v.getDiscount() - v.getTip()))
                .collect(Collectors.toList());
    }

    /**
     * 获取数据
     * @return
     */
    public List<HotelC> initList() {
        return new ArrayList<HotelC>() {
            {
                add(new HotelC("秘制奥利给", 1000d, 0.6, 20d, null));
                add(new HotelC("老八辣酱", 2000d, 0.6, 10d, null));
            }
        };
    }
}

 

 

这样就是一个简朴的计谋模式了,然则现在要挪用差别的实现类中的getMenuList方式,似乎照样离不开if else,那么现在就需要用工厂模式把所有实现类包装起来。

先界说一个枚举类,内里是各餐馆的code

public enum HotelEnum {

    HOTEL_A("HotelA"),
    HOTEL_B("HotelB"),
    HOTEL_C("HotelC"),;

    private String hotelCode;

    /**
     * 返回所有餐馆编码的聚集
     * @return
     */
    public static List<String> getList() {
        return Arrays.asList(HotelEnum.values())
                .stream()
                .map(HotelEnum::getHotelCode)
                .collect(Collectors.toList());
    }

    HotelEnum(String hotelCode) {
        this.hotelCode = hotelCode;
    }

    public String getHotelCode() {
        return hotelCode;
    }

}

 

 

接下来界说一个服务工厂,在静态块中行使反射机制把所有服务实现类动态加载到HOTEL_SERVER_MAP中,然后提供一个对外的获取对应服务的方式

这里有几个需要注重的地方:

1.由于包名是写死的,那么所有实现HotelService的实现类都需要放在牢固的包下

2.类名的花样也是牢固的,即枚举类中的hotelCode + "ServiceImpl"

/**
 * 服务工厂类
 */
public class HotelServerFactory {
    /**
     * 类路径目录
     */
    private static final String CLASS_PATH = "com.tactics.service.impl.";

    /**
     * 服务实现后缀
     */
    private static final String GAME_SERVICE_SUFFIX = "ServiceImpl";


    private static final Map<String, HotelService> HOTEL_SERVER_MAP = new ConcurrentHashMap<>();

    /**
     * 初始化实现类到COMPANY_SERVER_MAP中
     */
    static {
        HotelEnum.getList().forEach(v -> {
            String className = CLASS_PATH + v + GAME_SERVICE_SUFFIX;
            try {
                HOTEL_SERVER_MAP.put(v, (HotelService) Class.forName(className).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 获取餐馆服务实现
     *
     * @param hotelCode
     * @return
     */
    public static HotelService getHotelServerImpl(String hotelCode) {
        return HOTEL_SERVER_MAP.get(hotelCode);
    }
}

 

这里有一个问题,若是你的服务实现类是交给Spring容器治理的,内里有注入Mapper等等,使用反射的方式new出来的话,其中的属性是没有值的

Spring容器就相当于是一个工厂了,可以直接从Spring上下文中获取(怎么获取Spring上下文工具这里就不细说了,有需要可以自行百度)。

/**
 * 服务工厂类
 */
public class HotelServerFactory {
    /**
     * 类路径目录
     */
    private static final String CLASS_PATH = "com.tactics.service.impl.";

    /**
     * 服务实现后缀
     */
    private static final String GAME_SERVICE_SUFFIX = "ServiceImpl";

    /**
     * 获取餐馆服务实现
     *
     * @param hotelCode
     * @return
     */
    public static HotelService getHotelServerImpl(String hotelCode) {
        Class clazz = Class.forName(CLASS_PATH + hotelCode + GAME_SERVICE_SUFFIX);
        String className = hotelCode + GAME_SERVICE_SUFFIX;
        return (HotelService) ApplicationConfig.getBean(className, clazz);
    }
}

 

 

最终的挪用

public List server(String hotelCode) {
    //获取对应的服务
    HotelService hotelService = HotelServerFactory.getCompanyServerImpl(hotelCode);
    //获取经由逻辑盘算后返回的聚集列表
    return hotelService.getMenuList();
}

 

 

怎么样,是不是以为可读性,复用性和扩展性都大大提高了,营业扩展需要新加一个餐馆的时刻,只需要在枚举类中加一个hotelCode,然后界说一个实现类实现HotelService接口就好了,这个Demo也让我们知道了计谋模式和工厂模式在现实项目中的应用场景。

,

Allbet开户

欢迎进入Allbet开户(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

Allbet声明:该文看法仅代表作者自己,与本平台无关。转载请注明:欧博亚洲电脑版下载:运用设计模式告辞项目中大量臃肿的if else

网友评论

  • (*)

最新评论

文章归档

站点信息

  • 文章总数:668
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1076
  • 评论总数:245
  • 浏览总数:14718