1. 简单工厂模式
- 是类的创建模式, 又叫做静态工厂方法模式
- 由一个工厂对象决定创建出哪一种产品类的实例
简单工厂模式涉及到三个角色 :
- 工厂类(Creator)角色 : 工厂类在客户端的直接调用下创建产品对象, 它往往由一个具体Java类实现
- 抽象产品(Product)角色 : 由工厂方法模式所创建的对象的父类, 或它们共同拥有的接口. 抽象产品角色可以用一个Java接口或者Java抽象类实现.
- 具体产品(Concrete Product)角色 : 工厂方法模式所创建的任何对象都是这个角色的实例, 具体产品角色由一个具体Java类实现.
//抽象产品接口
public interface Product {
}
//具体产品类
public class ConcreteProduct implements Product {
public ConcreteProduct() {
}
}
//工厂类
public class Creator {
//静态工厂方法
public static Product factory() {
return new ConcreteProduct();
}
}
实际应用情况
- 如果产品有复杂的等级结构, 简单工厂模式一律使用同一个工厂类
- 好处是设计简单, 产品类的等级结构不会反映到工厂类中, 产品类的等级结构的变化也就不会影响工厂类,
- 缺点是增加新的产品必将导致工厂类的修改
- 如果具体产品类之间有共同的商业逻辑, 则公有逻辑应移到抽象角色中, 即此时抽象角色应由抽象类扮演, 反之应由Java接口扮演
- 每个工厂类可以有多个工厂方法, 分别负责创建不同的产品对象
- 如果系统仅有一个具体产品角色, 则可以省略抽象产品角色
//具体产品类
public class ConcreteProduct {
public ConcreteProduct() {
}
}
//工厂类
public class Creator {
//静态工厂方法
public static ConcreteProduct factory() {
return new ConcreteProduct();
}
}
- 有时候, 工厂角色可以由抽象产品角色扮演, 一个抽象产品类同时是子类的工厂
- 可以参考
DateFormat
类 - 这里引入针对抽象编程概念 : 这种将工厂方法的返回类型设置成抽象产品类型的做法, 叫做针对抽象编程
- 利用具体产品类的超类类型将它的真实类型隐藏起来, 提供了系统的可扩展性
- 如果将来有新的具体子类被加入系统中, 那么工厂类可以将返回给客户端的对象换成新的子类的实例, 而对客户端没有任何影响
- 可以参考
//抽象产品类
public abstract class Product {
...
//静态工厂方法
public static Product factory() {
return new ConcreteProduct();
}
}
//具体产品类
public class ConcreteProduct extends Product {
public ConcreteProduct() {
}
}
- 如果抽象产品角色已被省略, 工厂角色就可以与具体产品角色合并, 即三个角色合并为一个, 一个具体产品类为自身的工厂.
- 这种退化的简单工厂模式与单例模式及多例模式有相似之处, 但并不等同.
public class ConcreteProduct {
public ConcreteProduct() {
}
//静态工厂方法
public static ConcreteProduct factory() {
return new ConcreteProduct();
}
}
关于静态
- 其实工厂方法不用静态也可以, 只是用了静态方法后, 可以不用初始化工厂类而直接得到产品
- 抽象产品角色和工厂角色合并的情况必须使用静态工厂方法, 因为抽象类无法实例化
- 三角色合并的情况也要使用静态工厂方法, 如果方法为非静态, 则必须实例化具体产品类后才能调用工厂方法, 而既然已经能够实例化产品, 则再调用工厂方法就是多此一举.
- 综上所述, 对于简单工厂模式而言, 一般使用静态工厂方法
简单工厂模式的优点
- 该模式的核心是工厂类, 这个类含有必要的判断逻辑, 可以决定何时创建哪一个产品类的实例
- 而客户端可以免除直接创建产品对象的责任, 仅仅负责消费产品.
- 实现了对责任的分割.
简单工厂模式的缺点
- 工厂类集中了所有的产品创建逻辑, 成为了"上帝类", 责任过于集中, 如果该工厂类无法正常工作, 则其他模块都会受到影响.
- 何时创建何种产品的判断逻辑混合集中于工厂类中, 使得将来的功能扩展较为困难.
- 工厂方法使用静态方法, 而静态方法无法由子类继承, 因此工厂角色无法形成基于继承的等级结构.(
这一点在工厂方法模式中得到克服
) - 对"开闭原则"的支持有限
- 对于产品消费者来说, 需要某种产品时, 只需向工厂角色请求, 满足"开闭原则". 即消费者无需修改就可以接纳新的产品.
- 而对于工厂角色来说, 它必须知道每一种产品, 如何创建它们以及何时向客户端提供它们. 新增产品意味着必须修改工厂角色的源代码.