Java 设计模式--策略模式,枚举+工厂方法实现
项目中的一个页面跳转功能存在10个以上的if else判断,想要做一下整改
一、什么是策略模式
策略模式是对算法的包装,是把使用算法的责任和算法本身分割开来,委派给不同的对象管理,最终可以实现解决多重If判断问题。
1.环境(Context)角色:持有一个Strategy的引用。
2.抽象策略(Strategy)角色:这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口。
3.具体策略(ConcreteStrategy)角色:包装了相关的算法或行为。
(定义策略接口→实现不同的策略类→利用多态或其他方式调用策略。)
二、策略模式优缺点
优点:
算法可以自由切换(高层屏蔽算法,角色自由切换)
避免使用多重条件判断(如果算法过多就会出现很多相同的判断,很难维护)
扩展性好(可自由添加取消算法,而不影响整个功能)
缺点:
策略数量增多(每一个策略类复用性小,如果需要增加算法,就只能新增类)
所有的策略类都需要对外暴露(使用的人必须了解使用策略,这个就需要其他模式来补充,比如工厂模式、代理模式)
三、代码示例
1.定义共同的方法和行为
package com.ultiwill.strategy; public interface PayStrategy { /** * 共同的行为方法 * @return */ String toPayHtml(); }
2. 三种具体策略的实现 (阿里支付, 微信支付, 小米支付)
package com.ultiwill.strategy.impl; import com.ultiwill.strategy.PayStrategy; /** * @author chong.zuo * @date 2020/9/24 15:21 */ public class AliPayStrategy implements PayStrategy { @Override public String toPayHtml() { return "调用阿里支付...AliPayStrategy"; } }
package com.ultiwill.strategy.impl; import com.ultiwill.strategy.PayStrategy; /** * @author chong.zuo * @date 2020/9/24 15:29 */ public class WeChatPayStrategy implements PayStrategy { @Override public String toPayHtml() { return "调用微信支付...WeChatPayStrategy"; } }
package com.ultiwill.strategy.impl; import com.ultiwill.strategy.PayStrategy; /** * @author chong.zuo * @date 2020/9/24 15:34 */ public class XiaomiPayStrategy implements PayStrategy { @Override public String toPayHtml() { return "调用小米支付...XiaomiPayStrategy"; } }
3. 枚举类定义映射地址
package com.ultiwill.strategy.enums; import org.apache.commons.lang.StringUtils; /** * 枚举 * @author chong.zuo * @date 2020/9/24 15:45 */ public enum PayEnumStrategy { /** * 阿里支付 */ ALI_PAY("1","com.ultiwill.strategy.impl.AliPayStrategy"), /** * 微信支付 */ WECHAT_PAY("2","com.ultiwill.strategy.impl.WeChatPayStrategy"), /** * 小米支付 */ XIAOMI_PAY("3","com.ultiwill.strategy.impl.XiaomiPayStrategy"); private String code; private String className; PayEnumStrategy() { } PayEnumStrategy(String code, String className) { this.code = code; this.className = className; } public static String getClassNameByCode(String code) { String className = ""; if (StringUtils.isEmpty(code)) { return className; } for (PayEnumStrategy e : PayEnumStrategy.values()) { if (e.code.equalsIgnoreCase(code)) { className = e.className; break; } } return className; } public String getCode() { return code; } public String getClassName() { return className; } }
4.工厂类反射执行
package com.ultiwill.strategy.factory; import com.ultiwill.strategy.PayStrategy; import com.ultiwill.strategy.enums.PayEnumStrategy; /** * @author chong.zuo * @date 2020/9/24 16:10 */ public class StrategyFactory { /** * 使用策略工厂获取具体策略实现 * @param code * @return */ public static PayStrategy getPayStrategy(String code) { try { return (PayStrategy) Class.forName(PayEnumStrategy.getClassNameByCode(code)).newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } }
5.上下文获取具体策略
package com.ultiwill.strategy.context; import com.ultiwill.strategy.PayStrategy; import com.ultiwill.strategy.enums.PayEnumStrategy; import com.ultiwill.strategy.factory.StrategyFactory; import org.apache.commons.lang.StringUtils; /** * 上下文 * * @author chong.zuo * @date 2020/9/24 15:41 */ public class PayContextStrategy { /** * 获取具体的策略实现 * * @param code * @return */ public static String toPayHtml(String code) { if (StringUtils.isBlank(code)) { return "code不能为空..."; } PayStrategy payStrategy = StrategyFactory.getPayStrategy(code); if (payStrategy == null) { return "没有找到具体的策略..."; } return payStrategy.toPayHtml(); } }
四、测试
controller:
package com.ultiwill.controller; import com.ultiwill.strategy.context.PayContextStrategy; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @author c * @date 2020/5/14 9:59 */ @RestController public class TestController { @RequestMapping("/helloworld") public String hello(String code) { return PayContextStrategy.toPayHtml(code); /*if ("0".equals(code)) { return "调用阿里支付...AliPayStrategy"; } else if ("1".equals(code)) { return "调用微信支付...AliPayStrategy"; } else if ("2".equals(code)) { return "调用小米支付...AliPayStrategy"; } return "调用接口不存在"; */ } }
pom:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ultiwill</groupId> <artifactId>springboot-jar</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <version>2.1.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> <version>2.1.8.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.1.8.RELEASE</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.1.8.RELEASE</version> <configuration> <includeSystemScope>true</includeSystemScope> <mainClass>com.ultiwill.Application</mainClass> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
五、成功