背景:看了个demo工厂模式,示例代码的工厂类是new出来的,但是实际项目中都是用springboot框架、bean都是会给容器管理的,所以在思考这个工厂类要交给springboot托管要怎么改。以下是总结笔记

思考过程:看不懂工厂 -> 工厂用new -> 想改成bean注入,交给springboot管理

案例里提供两种实现方式:new 转成 依赖注入,交给springboot管理

难点:对依赖注入@Autowired理解不到位

1.工厂类用new实现
工厂模式:直接用new实现的代码
public class StoreFactory {
	 public ICommodity getCommodityService(Integer commodityType) {
	 if (null == commodityType) return null;
	 if (1 == commodityType) return new CouponCommodityService();
	 if (2 == commodityType) return new GoodsCommodityService();
	 if (3 == commodityType) return new CardCommodityService();
	 throw new RuntimeException("不存在的商品服务类型");
	 }
}
2.工厂类用springboot容器,依赖注入

难点:

  1. 不知道怎么把StoreFactory 变成bean :加@Component
  2. StoreFactory 变成bean之后要怎么往里面加入CouponCommodityService、GoodsCommodityService、CardCommodityService这些依赖到的bean:三种方式,@Autowired字段注入,构造器注入,set注入
  3. 压根不知道@Autowired还能标注在方法上:构造器注入和set注入都是@Autowired用来修饰方法的案例
  4. 这样的话,直接@Autowired标接口不就OK了?:是的,用字段注入就行

改用依赖注入的代码如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

public interface ICommodity {
    void sendCommodity();
}

@Service
public class CouponCommodityService implements ICommodity {
    @Override
    public void sendCommodity() {
        System.out.println("Coupon Commodity Service");
    }
}

@Service
public class GoodsCommodityService implements ICommodity {
    @Override
    public void sendCommodity() {
        System.out.println("Goods Commodity Service");
    }
}

@Service
public class CardCommodityService implements ICommodity {
    @Override
    public void sendCommodity() {
        System.out.println("Card Commodity Service");
    }
}

@Component
public class StoreFactory {

    private final CouponCommodityService couponCommodityService;
    private final GoodsCommodityService goodsCommodityService;
    private final CardCommodityService cardCommodityService;

    @Autowired
    public StoreFactory(CouponCommodityService couponCommodityService, 
                        GoodsCommodityService goodsCommodityService,
                        CardCommodityService cardCommodityService) {
        this.couponCommodityService = couponCommodityService;
        this.goodsCommodityService = goodsCommodityService;
        this.cardCommodityService = cardCommodityService;
    }

    public ICommodity getCommodityService(Integer commodityType) {
        if (commodityType == null) {
            return null;
        }
        switch (commodityType) {
            case 1:
                return couponCommodityService;
            case 2:
                return goodsCommodityService;
            case 3:
                return cardCommodityService;
            default:
                throw new RuntimeException("不存在的商品服务类型");
        }
    }
}

3.三种注入方式演示
@Component
public class BizService {

    //TODO 三种依赖注入方式

    @Value("${testFlag:0}")
    private Integer testFlag;

    //1.字段注入
    @Autowired
    private GoodsCommodityService goodsCommodityService;

    private CouponCommodityService couponCommodityService;
    private CardCommodityService cardCommodityService;


    //2.构造器注入
    @Autowired
    public BizService(CouponCommodityService couponCommodityService) {
        this.couponCommodityService = couponCommodityService;
    }

    //3.set注入(set注入不限置方法名是setxxx,spring是根据类型注入的)
    @Autowired
    public void cardCommodityServiceInject (CardCommodityService cardCommodityService) {
        this.cardCommodityService = cardCommodityService;
    }

    /**
     * 根据类型获取不同的Service 简单工厂
     * @param type
     * @return
     */
    public ICommodity getICommodityByType(Integer type) {
        System.out.println(testFlag);
        if(testFlag == 0) {
            System.out.println(0);
        } else {
            System.out.println(1);
        }
        switch (type) {
            case 1:
                return goodsCommodityService;
            case 2:
                return couponCommodityService;
            case 3:
                return cardCommodityService;
            default:
                return null;
        }
    }
}

4.其他总结
  1. @Component注解可以和 @Controller @Service @Repository互相替换。之所以常用后者是因为后者具备语义
  2. switch case的case用不了表达式、必须放已知的值。相比起if-else用在工厂模式里面,更直观
  3. 之前的在框架里使用到new但可以优化的例子:在项目里创建线程任务,用了new,依赖到的Service都是通过构造器传入的,很麻烦。现在应该直接用@Component修饰任务类,依赖的service直接@Autowired注入。最后要使用到任务类的时候就@Autowired字段注入就行
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐