意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
主要解决:在有多种算法相似的情况下,使用 if…else 所带来的复杂和难以维护。
何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
如何解决:将这些算法封装成一个一个的类,任意地替换。
关键代码:实现同一个接口。
优点: 1、算法可以自由切换。 2、避免使用多重条件判断。 3、扩展性良好。
缺点: 1、策略类会增多。 2、所有策略类都需要对外暴露。
spring两种方式可以将实现了同一接口的所有实现类注入map和list中
通过Spring将实现user的实现类都自动注入到userMap类中,
@Autowired
private List<IUser> userList;
@Autowired
private final Map<String, IUser> userMap = new ConcurrentHashMap<>();
public SimpleContext(Map<String, IUser> userMap) {
this.userMap.clear();
userMap.forEach((k, v)-> this.userMap.put(k, v));
}
实现IUser接口的类都会注入到userList中,userList中就有数据了有OneUser,TwoUser
private List<IUser> userList;
private final Map<String, IUser> userMap = new ConcurrentHashMap<>();
@Autowired
public void SimpleContext(Map<String, IUser> userMap) {
this.userMap.clear();
userMap.forEach((k, v)-> this.userMap.put(k, v));
}
@Autowired
public void aa(List<IUser> list){
this.userList=list;
}
通过上面特性可以做工厂模式
通过工厂来获取对应的策略
form工厂
@Service
public class AppFormFactory {
private static final Map<String, IAppForm> STRATEGY_MAP = new ConcurrentHashMap<>();
public AppFormFactory(Map<String, IAppForm> map){
STRATEGY_MAP.clear();
map.forEach((k,v)->STRATEGY_MAP.put(v.getAppType(),v));
}
public static IAppForm getInstance(String appType){
return STRATEGY_MAP.get(appType);
}
}
抽象方法提取公共部分,返回不同(可以不需要)
public abstract class AppFormAbstract implements IAppForm {
public abstract String getAppType() ;
@Override
public JsonResult initBpm(Boolean isNeedinitBpmDef,Map<String, List<FormPcDto>> mappc) {
if(isNeedinitBpmDef == null || isNeedinitBpmDef) {
//调用初始化一个流程定义
JsonResult dpmResult = SpaceUtil.doActOriginal(TokenUtil.getToken(), JSON.toJSONString(mappc));
if (Objects.isNull(dpmResult) || dpmResult.getCode() == JsonResult.FAIL_CODE) {
return JsonResult.Fail("初始化流程定义失败!");
}
return dpmResult;
}
return JsonResult.Success("不需要初始化");
}
@Override
public abstract String backAppInterface(JSONObject jsonObject);
}
n个实现类
@Service
public class WorkOrderForm extends AppFormAbstract {
private final static String WORKORDER_APP_TYPE="wordOrder";
@Override
public String getAppType() {
return WORKORDER_APP_TYPE;
}
@Override
public String backAppInterface(JSONObject jsonObject) {
xxxxxxx;
}
}
@Service
public class LightServiceForm extends AppFormAbstract {
private final static String LIGTH_APP_TYPE="lightApp";
@Override
public String getAppType() {
return LIGTH_APP_TYPE;
}
@Override
public String backAppInterface(JSONObject jsonObject) {
xxxxxx
}
}
使用
IAppForm appForm=AppFormFactory.getInstance(StringUtils.isNotEmpty(serviceType)?serviceType:SpaceUtil.SERVICE_TYPE_WORD_ORDER);
//是否需要
Boolean needInitPmDef=json.getBoolean("isNeedInitBpmDef");
JSONObject backObject=new JSONObject();
JsonResult dpmResult=appForm.initBpm(needInitPmDef,mappc);
str=appForm.backAppInterface(backObject);
上述也是aba\abab解决方案
if(a){
A
}else if(b){
B
}else{
A
}
工厂类中提供一个静态方法,可以把策略类put到一个map中。
public class ChangeRequirementStatusFactory {
//该map放置具体实现类实例,key为类型,value为实例对象
public static Map map = new HashMap<>();
//提供放置type和实现类的方法
public static void putChangeRequirementStatusAbstract(Integer type, ChangeRequirementStatusAbstract userAbstract) {
map.put(type, userAbstract);
}
//获取bean实例
public static ChangeRequirementStatusAbstract getChangeRequirementStatusAbstract(Integer type) {
return map.get(type);
}
}
在策略接口下建立一个抽象类或者中介实现类来实现InitializingBean接口
public class ChangeRequirementStatusAbstractImpl implements ChangeRequirementStatusAbstract, InitializingBean {
public Integer type;
//bean加载时执行的方法
@Override
public void afterPropertiesSet() throws Exception {
//将实现类和type放置到map中
ChangeRequirementStatusFactory.putChangeRequirementStatusAbstract(type, this);
}
继承ChangeRequirementStatusAbstractImpl 的类,打上@Service注解后,bean初始化时会执行afterPropertiesSet()
工厂类中的put就有各个实现类的Bean,完成工厂策略构建。
postProcessBeforeInitialization -> initializingBean -> postProcessAfterInitialization,从顺序中也很好看出来,InitializingBean发挥作用的时机就在这两个方法之间。
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
这个接口就是这么的简单,只有这么一个方法,目的就是进一步调整实例的状态。
afterPropertiesSet发生作用的时机是当前类的实例化的时候,而BeanPostProcessor则是所有类,这也是为什么afterPropertiesSet的函数中没有参数
接口中有一个方法提供了singleton类型的对象实例销毁之前执行的销毁逻辑。
public interface DisposableBean {
void destroy() throws Exception;
}
DisposableBean则提供了singleton 类型的 bean 的销毁逻辑