简介
本文介绍工厂模式的抽象工厂模式。
抽象工厂:用来生产其他工厂的工厂。
适用场景
抽象工厂适用于多个品牌、多种产品类型的情况。
优缺点
优点
管理多个品牌、多个类型时,很方便。
缺点
增加新的产品类型时比较麻烦。
源码中的应用
- 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 工厂类的方法用工厂模式中的简单工厂模式来写。即:传入想要的工厂,比如“小米”这个字符串,然后生产工厂的类来创建小米工厂。但是,这样的话,就像我们工厂模式介绍的那样,不如使用工厂方法模式。
请先
!