简介
本文介绍工厂模式的抽象工厂模式。
抽象工厂:用来生产其他工厂的工厂。
适用场景
抽象工厂适用于多个品牌、多种产品类型的情况。

优缺点
优点
管理多个品牌、多个类型时,很方便。
缺点
增加新的产品类型时比较麻烦。
源码中的应用
- Spring中IOC容器创建/管理Bean对象
- 反射中Class对象的newInstance方法
- JDBC中的Connection对象的获取
- JDK中Calendar的getInstance方法
实例
需求:如上边“适用场景”所示,提供小米和华为两个品牌,手机和路由器两种类型。
代码结构

手机产品
接口
package com.knife.designPattern.product.phone;
public interface Phone {
/**
* 打电话
*/
String callUp();
}
小米实现类
package com.knife.designPattern.product.phone.impl;
import com.knife.designPattern.product.phone.Phone;
import lombok.Data;
@Data
public class XiaoMiPhoneImpl implements Phone {
/**
* CPU个数
*/
private Integer cpuCount;
/**
* 内存大小
*/
private Integer memoryStorage;
public XiaoMiPhoneImpl(Integer cpuCount, Integer memoryStorage) {
this.cpuCount = cpuCount;
this.memoryStorage = memoryStorage;
}
@Override
public String callUp() {
return "小米手机打电话";
}
}
华为实现类
package com.knife.designPattern.product.phone.impl;
import com.knife.designPattern.product.phone.Phone;
import lombok.Data;
@Data
public class HuaWeiPhoneImpl implements Phone {
/**
* CPU个数
*/
private Integer cpuCount;
/**
* 内存大小
*/
private Integer memoryStorage;
public HuaWeiPhoneImpl(Integer cpuCount, Integer memoryStorage) {
this.cpuCount = cpuCount;
this.memoryStorage = memoryStorage;
}
@Override
public String callUp() {
return "华为手机打电话";
}
}
路由器产品
接口
package com.knife.designPattern.product.router;
public interface Router {
/**
* 接收网络数据
*/
String receiveNetworkData();
}
小米实现类
package com.knife.designPattern.product.router.impl;
import com.knife.designPattern.product.router.Router;
import lombok.Data;
@Data
public class XiaoMiRouterImpl implements Router {
/**
* 网速
*/
private Integer networkSpeed;
/**
* 插口数量
*/
private Integer slotCount;
public XiaoMiRouterImpl(Integer networkSpeed, Integer slotCount) {
this.networkSpeed = networkSpeed;
this.slotCount = slotCount;
}
@Override
public String receiveNetworkData() {
return "小米路由器接收网络数据";
}
}
华为实现类
package com.knife.designPattern.product.router.impl;
import com.knife.designPattern.product.router.Router;
import lombok.Data;
@Data
public class HuaWeiRouterImpl implements Router {
/**
* 网速
*/
private Integer networkSpeed;
/**
* 插口数量
*/
private Integer slotCount;
public HuaWeiRouterImpl(Integer networkSpeed, Integer slotCount) {
this.networkSpeed = networkSpeed;
this.slotCount = slotCount;
}
@Override
public String receiveNetworkData() {
return "华为路由器接收网络数据";
}
}
工厂
接口
package com.knife.designPattern.factory;
import com.knife.designPattern.product.phone.Phone;
import com.knife.designPattern.product.router.Router;
public interface ProductFactory {
Phone createPhone();
Router createRouter();
}
小米实现类
package com.knife.designPattern.factory.impl;
import com.knife.designPattern.factory.ProductFactory;
import com.knife.designPattern.product.phone.Phone;
import com.knife.designPattern.product.phone.impl.XiaoMiPhoneImpl;
import com.knife.designPattern.product.router.Router;
import com.knife.designPattern.product.router.impl.XiaoMiRouterImpl;
public class XiaoMiFactoryImpl implements ProductFactory {
public Phone createPhone() {
return new XiaoMiPhoneImpl(4, 21);
}
@Override
public Router createRouter() {
return new XiaoMiRouterImpl(100, 5);
}
}
华为实现类
package com.knife.designPattern.factory.impl;
import com.knife.designPattern.factory.ProductFactory;
import com.knife.designPattern.product.phone.Phone;
import com.knife.designPattern.product.phone.impl.HuaWeiPhoneImpl;
import com.knife.designPattern.product.router.Router;
import com.knife.designPattern.product.router.impl.HuaWeiRouterImpl;
public class HuaWeiFactoryImpl implements ProductFactory {
public Phone createPhone() {
return new HuaWeiPhoneImpl(4, 21);
}
@Override
public Router createRouter() {
return new HuaWeiRouterImpl(100, 5);
}
}
测试类
package com.knife.designPattern.controller;
import com.knife.designPattern.factory.ProductFactory;
import com.knife.designPattern.factory.impl.HuaWeiFactoryImpl;
import com.knife.designPattern.factory.impl.XiaoMiFactoryImpl;
import com.knife.designPattern.product.phone.Phone;
import com.knife.designPattern.product.router.Router;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Api(tags = "产品")
@RestController
@RequestMapping("product")
public class ProductController {
@ApiOperation("手机")
@GetMapping("phone")
public String phone(String name) {
ProductFactory productFactory = null;
switch (name) {
case "华为":
productFactory = new HuaWeiFactoryImpl();
break;
case "小米":
productFactory = new XiaoMiFactoryImpl();
break;
default:
return null;
}
Phone phone = productFactory.createPhone();
if (phone != null) {
return phone.callUp();
}
return null;
}
@ApiOperation("路由器")
@GetMapping("router")
public String router(String name) {
ProductFactory productFactory = null;
switch (name) {
case "华为":
productFactory = new HuaWeiFactoryImpl();
break;
case "小米":
productFactory = new XiaoMiFactoryImpl();
break;
default:
return null;
}
Router router = productFactory.createRouter();
if (router != null) {
return router.receiveNetworkData();
}
return null;
}
}
源码下载
此隐藏内容仅限VIP查看升级VIP
测试
访问:http://localhost:8080/doc.html(当然,你用Postman也完全可以)
测试结果:


思考
咦?不是说抽象工厂是生产其他工厂的工厂吗?我怎么,还是在new 工厂类?并没有生产工厂呀?
实际上,我们可以将上边直接new 工厂类的方法用工厂模式中的简单工厂模式来写。即:传入想要的工厂,比如“小米”这个字符串,然后生产工厂的类来创建小米工厂。但是,这样的话,就像我们工厂模式介绍的那样,不如使用工厂方法模式。

请先 !