简单工厂模式

本系列总结的设计模式,皆在实际的生产项目中有实际的运用,实例也皆为项目中的例子。

场景

需要将net 项目中的一个推荐接口,迁移到java 。

推荐接口的内容是根据不同的类型做出不同的推荐,历史的net代码冗余太多,大概有7,8个if...呈现在主方法里。每个if里有在相应的biz类中有对应的业务代码。

如果有新的类型推荐,则会在主方法里新增一个if()...然后再相应的biz  里写业务代码。

if (request.type = "A")
{
    //recommend plane
    return response;
}
if (request.type = "B")
{
    //recommend bus
    return response;
}
if(request.type = "R")
{
    //recommend round plane
    return response;
}
// C,X ....

形成原因

相信所有的业务系统都会有类似的代码,新增一个类型,用if()..可以快速实现逻辑。这样也没有什么问题。

自己也分析了下,为什么业务系统代码普遍代码质量不高的原因。

  1.逻辑需要快速实现,怎么方便怎么来

  2. 整体的业务系统没有定义一个清晰的代码规则和编码约束。

  3. coder的技术水平层次不齐。

迁移改造

这种场景决定用抽象工厂去做相应的改造,根据不同的recommendType 来做出相应的推荐。每种type对应有自己的实现子类.

Factory类 根据recommenType 去找到对应的子类。

/**
 * Created by liyangyang on 2017/10/18.
 */
@Service
public class RecommendInfoFactory implements IRecommendInfoFactory {
    @Autowired
    @Qualifier("A")
    private RecommendInfoOfTypeA recommendInfoOfTypeA;

    @Autowired
    @Qualifier("B")
    private RecommendInfoOfTypeB recommendInfoOfTypeB;

    @Autowired
    @Qualifier("Default")
    private RecommendInfoOfTypeDefault recommendInfoOfTypeDefault;

    @Autowired
    @Qualifier("H")
    private RecommendInfoOfTypeH recommendInfoOfTypeH;

    @Autowired
    @Qualifier("NJSH")
    private RecommendInfoOfTypeNJSH recommendInfoOfTypeNJSH;

    @Autowired
    @Qualifier("R")
    private RecommendInfoOfTypeR recommendInfoOfTypeR;

    @Autowired
    @Qualifier("X")
    private RecommendInfoOfTypeX recommendInfoOfTypeX;

    @Autowired
    @Qualifier("KT")
    private RecommendInfoOfTypeKongTie recommendInfoOfTypeKongTie;

    @Override
    public IRecommendInfo getInstance(String recommendType) {
        IRecommendInfo recommendInfo;
        //根据推荐类型,判断推荐内容
        switch (recommendType){
            case "A":
                recommendInfo = recommendInfoOfTypeA;
                break;
            case "B":
                recommendInfo = recommendInfoOfTypeB;
                break;
            case "H":
                recommendInfo = recommendInfoOfTypeH;
                break;
            case "R":
                recommendInfo = recommendInfoOfTypeR;
                break;
            case "X":
                recommendInfo = recommendInfoOfTypeX;
                break;
            case "NJSH":
                recommendInfo = recommendInfoOfTypeNJSH;
                break;
            case "KT":
                recommendInfo = recommendInfoOfTypeKongTie;
                break;
            default:
                recommendInfo = recommendInfoOfTypeDefault;
                break;
        }
        return recommendInfo;
    }
}

推荐的主方法:

public GetRecommendListResponseType getRecommendList(GetRecommendListRequestType request)
{
    //根据不同的recommendType 去找到对应的实现子类
    IRecommendInfo recommendInfo = recommendInfoFactory.getInstance(request.getRecommendType());
    //调用实现子类的逻辑得到对应的推荐
    GetRecommendListResponseType response = recommendInfo.getRecommend(request, cityInfo, distance, addition);
    
    return response;
}

相应的实现子类 A , B , C 。。。:

/**
 * Created by liyangyang on 2017/10/18.
 */
@Service
@Qualifier("A")
public class RecommendInfoOfTypeA implements IRecommendInfo{
    @Autowired
    private IGetRecommendListCommonBiz getRecommendListCommonBiz;

    @Override
    public GetRecommendListResponseType getRecommend(GetRecommendListRequestType request, RecommendInfoOfCityEntity cityInfo, double distance,
                                                     HashMap<String,String> addition) {
        GetRecommendListResponseType responseType = new GetRecommendListResponseType();
        List<RecommendInfo> recommendInfos = Lists.newArrayList();

        //推荐机票
        RecommendInfo recommendInfo = getRecommendListCommonBiz.getRecommendPlane(request, cityInfo, distance,addition);
        if (!Objects.isNull(recommendInfo)) {
            recommendInfos.add(recommendInfo);
            responseType.setRecommendList(recommendInfos);
        }

        return responseType;
    }
}

优点

 1. 相比 net 中的 if()... 形式,每个子类都对应自己的职责,职责和对应的代码结构更清晰。

 2. 新增一个recommendType, 只需新增对应的实现子类。基本满足对扩展开放,对更改封闭。

缺点

 1. 类文件太多。

 2. 新增一个recommendType, 还需要在Factory类中,新增一个case 来实现子类的路由。没有满足更改封闭。

改进

 1. 用抽象工厂 + 反射 来自动路由相应的子类。但反射对应的效率会是个瓶颈。

PS: java 中的多态实现:一个接口对应不同的实现。比如A,B,C 实现同一个接口。

      java 中spring boot 容器是以接口的形式注入到容器中的。 默认是一个接口只有一个实现类。这样自动装配的时候,就会默认去找到接口对应的实现。

      但如果 一个接口有N个子类实现,spring boot 容器装配的时候就会出错。因为它不知道去装配那个子类。

      在相应的子类上添加 @Qualifier("A") 注解注入,装配的时候也加上 @Qualifier("A") 。

      对应解释: https://www.cnblogs.com/smileLuckBoy/p/5801678.html

六度与心 修行苦 苦修行
原文地址:https://www.cnblogs.com/hdtechnology/p/8734357.html