一、简单工厂模式
1. 定义
- 简单工厂模式又名静态方法工厂模式,是由一个工厂对象决定创建出哪一种产品类的实例
2. UML类图

- 抽象产品类(IProduct):创建的所有对象的父类,它负责描述所有实例所共有的公共接口
- 产品工厂类(SimpleFactory):负责生产各种具体的产品,不关心产品产生的过程,只关心要生产的产品的类型
- 具体产品类(Product):具体的产品,封装了产品建造的过程以及使用的教程
3. 使用场景
- 工厂类负责创建的对象比较少。
- 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心
4. 简单实现
- 需求:不同手机型号需要使用不同的推送,可以集成小米、华为、极光推送然后创建一个工厂类根据手机型号来使用不同的推送
- 1、定义推送调用的接口
interface IPush {
fun push()
}
class MiPush : IPush {
override fun push() {
println("小米手机使用小米推送")
}
}
class HuaWeiPush : IPush {
override fun push() {
println("华为手机使用华为推送")
}
}
class JiGuangPush : IPush {
override fun push() {
println("其他手机使用极光推送")
}
}
object PushFactory {
fun createPush(type: String): IPush {
return when (type) {
"xiaoMi" -> MiPush()
"huaWei" -> HuaWeiPush()
else -> JiGuangPush()
}
}
}
class CreatePush {
companion object {
@JvmStatic
fun main(args: Array<String>) {
PushFactory.createPush("xiaoMi").push()
PushFactory.createPush("huaWei").push()
}
}
}
运行结果:
小米手机使用小米推送
华为手机使用华为推送
5. 优缺点
- 优点:用户根据参数获得对应的类实例,避免了直接实例化类,降低了耦合性节
- 缺点:类型在编译期间已经被确定,增加新类型需要修改工厂,违背了开放封闭原则(ASD) ;需要事先知道所有要生成的类型,当子类过多或者子类层次过多时不适合使用
二、工厂方法模式
1. 定义
- 定义一个用于创建对象的接口,让子类决定实例化哪个类
2. UML类图

- Product:抽象产品类。
- ConcreteProduct:具体产品类,实现Product接口。
- Factory:抽象工厂类,该方法返回一个Product类型的对象。
- ConcreteFactory:具体工厂类,返回ConcreteProduct实例
3. 使用场景
- 在任何需要生成复杂对象的地方,都可以使用工厂方法模式
- 复杂对象适合使用工厂模式,用new就可以创建的简单对象无需使用工厂方法模式
4. 简单实现
- 新需求:在原来基础上,oppo手机需加入oppo推送,而且后面可能还会有更多手机厂商的推送...
- 1、在原来的基础上加一层抽象工厂类
abstract class AbsPushFactory {
abstract fun <T : IPush> createPush(clazz: Class<T>): T
}
- 2、原来的工厂类继承抽象工厂类利用反射来初始化各产品对象
object PushFactory : AbsPushFactory() {
override fun <T : IPush> createPush(clazz: Class<T>): T {
return Class.forName(clazz.name).getDeclaredConstructor().newInstance() as T
}
}
- 3、这里跟以前小米华为一样,添加oppo推送的具体产品类......
class OppoPush : IPush {
override fun push() {
println("oppo手机使用oppo推送")
}
}
class CreatePush {
companion object {
@JvmStatic
fun main(args: Array<String>) {
PushFactory.createPush(MiPush::class.java).push()
PushFactory.createPush(HuaWeiPush::class.java).push()
PushFactory.createPush(OppoPush::class.java).push()
}
}
}
运行结果:
小米手机使用小米推送
华为手机使用华为推送
oppo手机使用oppo推送
5. 源码中的使用场景
- Activity中的onCreate方法通过setContentView设置布局
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new LinearLayout(this));
}
}
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return new Binder();
}
}
5. 优缺点
- 优点:可以自由新增更多的产品线而不破坏开放封闭原则
- 缺点:使用反射,多多少少影响性能
三、抽象工厂模式
1. 定义
- 为创建一组相关或者相互依赖的对象提供一个接口,而无需指定它们的具体类
2. UML类图

- AbstractFactory:抽象工厂,它声明了用来创建不同产品的方法
- ConcreteFactory:具体工厂,实现抽象工厂中定义的创建产品的方法,生成一组具体产品
- AbstractProduct:抽象产品,为每种产品声明业务方法
- ConcreteProduct:具体产品,定义具体工厂生产的具体产品,并实现抽象产品中定义的业务方法
3. 使用场景
- 一个系统不依赖于产品线实例如何被创建、组合和表达的细节
- 系统中有多于一个的产品线,而每次只使用其中某一产品线
- 一个产品线(或是一组没有任何关系的对象)拥有相同的约束
4. 简单实现
- 新需求:添加针对向不同的手机厂商发短信
- 1、添加一个Isend接口
interface ISend {
fun send()
}
class MiSend : ISend {
override fun send() {
println("小米手机发送小米短信")
}
}
abstract class AbsPushSendFactory {
abstract fun createPush(): IPush
abstract fun createSend(): ISend
}
- 4、分别实现小米工厂和华为工厂(华为工厂代码类似已省略)
class MiFactory : AbsPushSendFactory() {
override fun createPush(): IPush {
return MiPush()
}
override fun createSend(): ISend {
return MiSend()
}
}
class CreatePushSend {
companion object {
@JvmStatic
fun main(args: Array<String>) {
val miFactory = MiFactory()
miFactory.createPush().push()
miFactory.createSend().send()
val huaWeiFactory = HuaWeiFactory()
huaWeiFactory.createPush().push()
huaWeiFactory.createSend().send()
}
}
}
运行结果:
小米手机使用小米推送
小米手机发送小米短信
华为手机使用华为推送
华为手机发送华为短信
5. 优缺点
- 优点:具体类的创建实例过程与客户端分离,客户端通过工厂的抽象接口操纵实例,客户端并不知道具体的实现是谁
- 缺点:增加新的产品族则也需要修改抽象工厂和所有的具体工厂
四. 三种工厂模式对比
- 简单工厂模式:产品线固定;
工厂类,无抽象工厂类
- 工厂方法模式:单一产品线可延伸产品(添加产品,只需添加IProduct的新产品实现类即可);
一个抽象工厂类,所有产品共用一个工厂类
- 抽象工厂模式:固定多产品线可延伸产品(添加产品,需添加IProduct的新产品实现类以及新产品的工厂类);
一个抽象工厂类,每一个产品都有一个工厂类