理解工厂模式
1 通用模型
抽象类Product, AbstractFactory, 具体类ConcreteProduct, Factory. 用户调用工厂模式编写的API时, 只要知道Product抽象类以及具体类的名称, 就能让Factory实例给创建一个具体类出来, 无需知道Factory如何创建.
2 优点
- 封装性: 调用者只要知道Product抽象类以及具体类的名称, 就能让Factory 实例给创建一个具体类出来.
- 扩展性: 增加一种Product时适当修改Factory代码就行
- 对使用者屏蔽了产品类的创建过程, 隐藏了如何实现.
- 使得切换一套产品更方便了, 只要换一个工厂就行
- 保证了产品的一致性, 例如有些产品要求只能与同系列的其他产品一起用, 如果由用户自己创建类, 可能会出现不同Family的产品共用的情况.
3 使用场景
这里所谓的产品其实就是一个类, 所以理论上任何需要创建对象的地方都可以用工厂模式, 但是具体产品由于继承自同一个产品抽象类, 所以要求具体的产品有一些共性. 也就是说, 如果你设计的软件有多个类是并列关系, 例如邮件协议POP3, IMAP, HTTP, 就适合用工厂模式, 另外还要求创建对象的逻辑比较复杂, 不然也不必专门使用工厂模式增加代码复杂度.
适用于换一个config就换一套类似的东西的场景, 例如配置换一种数据库, 配置换一种风格. 只要换一个factory就能实现这样的功能.
例子
根据网页风格有两种factory, 都实现了createWindow和createWidget方法, 但是返回的是不同风格的组件. 而在上层代码中, 如果要修改风格只要改一行代码就行, 即换一个factory
4 疑惑
-
Q: Product p = factory.createproduct(ConcreteProduct)和直接Product p = new ConcreteProduct()有什么区别?
A: 对于复杂的类, 无法简单的一句new ConcreteProduct就能完成创建产品的工作, 可能需要多行, 而如果后续需要修改创建的流程时, 就要对每处创建的地方的多行代码进行修改, 使用工厂模式只要改工厂类就行. 相当于说, 由于创建一个产品的代码收到业务逻辑的影响较大, 可能经常会改动, 于是创建产品的代码放到了一个专门的地方, 也就是工厂类. 例如, 如果需要换成单例模式了, 只要修改工厂的代码就行, 而不必对每一处创建产品的代码进行修改.
-
Q: 为什么要AbstractFactory, 直接一个Factory类不就行了吗?
A: 因为创建产品的逻辑复杂, 可能这几个地方需要用这种逻辑创建产品, 另几个地方需要另一种逻辑创建产品, 因此需要AbstractFactory, 多种逻辑就有多种不同Factory, 用的时候根据需要选用不同的Factory. 如果不需要多种逻辑来创建产品, 可以不用AbstractFactory.