我恰芙蓉王资料

本文主要介绍我恰芙蓉王资料 方法和在新技术下所面对的“挑战”,方便大家深入理解我恰芙蓉王资料 过程。本文也将分享我恰芙蓉王资料 所遇到的问题和应对策略,怎么解决怎么做的问题。
通过深入本文可以理解代码原理,进行代码文档的下载,也可以查看相应 Demo 部署效果。

前言

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

代码中使用了大量的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也让我们知道了策略模式和工厂模式在实际项目中的应用场景。

我恰芙蓉王资料部分资料来自网络,侵权毕设源码联系删除

区块链毕设网(www.qklbishe.com)全网最靠谱的原创区块链毕设代做网站
部分资料来自网络,侵权联系删除!
资源收费仅为搬运整理打赏费用,用户自愿支付 !
qklbishe.com区块链毕设代做网专注|以太坊fabric-计算机|java|毕业设计|代做平台 » 我恰芙蓉王资料

提供最优质的资源集合

立即查看 了解详情