根据输入条件来由工厂动态产生符合条件的策略类对象,并调用相应策略方法实现功能
这么说可能有点抽象举一个例子,比如我们在生活中的自动售货机一样,他的电子屏幕上面展示不同的商品,当我们选择具体的商品后支付,售货机就会给我们相应的商品。这里 选择商品=输入条件,售货机=策略工厂类,我们保证条件在策略工厂中有具体的实现即可,这样策略工厂就能根据具体的条件来保证能拿到不同的策略实现类,再调用方法
使用场景因为设计模式更多偏向于编程上的设计理念,应用场景本人也是用的不多,主要是储备以防不时之需,如果有大神不吝赐教的话万分感激,我这里主要用于多层if…else逻辑方案判断执行的解耦,比如考虑到后期的业务拓展,逻辑判断就会再次增加,需要在代码上修改,不管从扩展性还是代码整洁上看都不合适
原代码:
if(status == 0){
//.....条件执行逻辑A
}else if(status == 1){
//.....B
}else if(status == 2){
//.....C
}
思路:
1.定义接口,不同条件下的执行封装成具体的接口实现类
2.由工厂统一管理策略实现类,根据策略的不同返回具体的实现类
接口类
public interface RefundInterface {
void refund(OmOrdersBO omOrdersBO);
}
策略实现类
public class RefundZero implements RefundInterface {
@Override
public void refund(OmOrdersBO omOrderSBO, RedisTemplate redisTemplate) {
// ....A具体实现逻辑A
}
}
public class RefundOne implements RefundInterface {
@Override
public void refund(OmOrdersBO omOrderSBO) {
// ...具体实现逻辑B
}
}
public class RefundTwo implements RefundInterface {
@Override
public void refund(OmOrdersBO omOrderSBO) {
// ...具体实现逻辑C
}
}
工厂类
public class RefundStrategyFactory {
private static final Map map = new HashMap<>();
// 使用map进行存储策略类,后期再有扩展只需要增加具体的键值对
static {
map.put(OrderType.ZERO.ordinal(), new RefundZero());
map.put(OrderType.ONE.ordinal(), new RefundOne());
map.put(OrderType.TWO.ordinal(), new RefundTwo());
}
public static RefundInterface getRefundStrategy(Integer type) {
return map.get(type);
}
工厂类构建完成,原来代码用RefundStrategyFactory.getRefundStrategy(Integer type)方法获得具体实现类,接口接收实现类,调用接口方法=具体的实现类方法
优化实现了策略工厂模式的设计,优化了if…else的冗余结构后,再回过头来看看是否有优化的地方。定位工厂类,这里我们是用map存放具体的策略实现类,没有具体的动态实现,后期添加也还要继续添加
采用反射+注解的方式来对工厂类进行优化
1.自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Refund {
int number() default 0;
}
2.给实现类加注解(附带相应条件)
@Component
@Refund(number = 0)
public class RefundZero implements RefundInterface {
@Override
public void refund(OmOrdersBO omOrderSBO, RedisTemplate redisTemplate) {
// ....A具体实现逻辑A
}
}
@Component
@Refund(number = 1)
public class RefundOne implements RefundInterface {
@Override
public void refund(OmOrdersBO omOrderSBO) {
// ...具体实现逻辑B
}
}
@Component
@Refund(number = 2)
public class RefundTwo implements RefundInterface {
@Override
public void refund(OmOrdersBO omOrderSBO) {
// ...具体实现逻辑C
}
}
3.工厂类
这里工厂类做的事情主要分为几部分:
1.构造方法-执行获取策略类集合方法(拿到所有被注解的策略类)
2.getStrategyRefund(Integer refundType)方法–for遍历策略类集合,判断策略类上的注解参数是否和输入条件一致,一致则获取类的实例对象
此时就得到了具体的策略工厂实现类
ps:这里策略工厂类RefundStrategyFactory和具体的实现类放一个包下,自己也可以去修改扫描路径
public class RefundStrategyFactory {
private static final String PACKAGE = RefundStrategyFactory.class.getPackage().getName();
private List> refundList = new ArrayList<>();
private ClassLoader classLoader = getClass().getClassLoader();
public static RefundStrategyFactory getInstance() {
return FactoryInstance.instance;
}
public static class FactoryInstance {
private static RefundStrategyFactory instance = new RefundStrategyFactory();
}
public RefundStrategyFactory() {
//构造方法-----获取策略类集合
getRefundList();
}
private List> getRefundList() {
Class refundClazz = null;
File[] resources = getResources();
try {
refundClazz = (Class) classLoader.loadClass(RefundInterface.class.getName());
} catch (ClassNotFoundException e) {
throw new RuntimeException("未找到策略接口");
}
for (int i = 0; i < resources.length; i++) {
Class> clazz = null;
try {
clazz = classLoader.loadClass(PACKAGE + "." + resources[i].getName().replace(".class", ""));
if (RefundInterface.class.isAssignableFrom(clazz) && clazz != refundClazz) {
refundList.add((Class extends RefundInterface>) clazz);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return null;
}
private File[] getResources() {
try {
String SCAN_PACKAGE = RefundStrategyFactory.class.getPackage().getName();
File file = new File(classLoader.getResource(SCAN_PACKAGE.replace(".", "/")).toURI());
return file.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
if (pathname.getName().endsWith(".class")) {
return true;
}
return false;
}
});
} catch (URISyntaxException e) {
throw new RuntimeException("未找到策略资源");
}
}
public RefundInterface getStrategyRefund(Integer refundType) {
for (Class extends RefundInterface> clazz : refundList) {
Refund annotation = clazz.getAnnotation(Refund.class);
if (annotation.number() == refundType) {
try {
return clazz.newInstance();
} catch (Exception e) {
throw new RuntimeException("策略类获取失败");
}
}
}
return null;
}
}



