工厂模式¶
字数 723 个 代码 121 行 阅读时间 4 分钟 访问量
警告:当前页面内容仍处于草稿状态!
工厂模式可以简单理解为一种动态创建实例的模式。何为工厂?通俗意义上的工厂是一个生产建筑,而在设计模式中,这里的工厂生产的产品就是类的实例。普通的静态创建实例就是实例化给定的类,但当我们在定义阶段无法确定需要实例化哪个类的时候,就应该使用工厂模式在运行时地动态地创建实例。
下面是一个简单情景:
假设我们需要根据用户输入的字符串去绘制不同的图形:
现在假设绘制这些图形的操作就是创建不同的形状类的实例,那么你把它封装起来它就变成了一个工厂了,一个根据指定的字符串生产不同形状类实例的工厂。
flowchart LR
0([用户输入])
1[形状类工厂]
2([形状实例])
0 --str--> 1 --instance--> 2 大致就如上图那样。现在我们把它的封装写出来:
猜你想问:为什么不直接传入类型而是要传入字符串呢?使用类型不是更加准确吗?
首先,需要注意一点的是,工厂模式是动态创建实例,它这个动态不仅仅是在于类型的动态,而是更加宽泛的,输入是动态的。也就说,调用者在事先并不知道有哪些类型可以被“生产”出来。
如果说,需要更加准确一点的写法,应该是限定输入的范围,告知调用者,能“生产”的类型有哪些,比如:
上面提供了两种优化思路,一种是利用类型注解进行君子约定,告知调用者应该传入哪些值。但更好的做法是第二种,通过枚举强制约束,传入其它非预期的值将引发 ValueError。以上代码中,以单下划线开头的类属于约定上的保护类,对外应该不可见,此时可以任务调用者无法知道实际的类型有哪些,只能通过工厂进行调用。
对于无状态需要维护的(没有配置这种),非动态创建的工厂(即抽象工厂生产的工厂,抽象工厂模式会讲)一般会结合使用后面会讲到的单例模式,因为这些工厂不需要多个不同的实例,或者说创建多个不同的工厂实例没有意义。在 Python 中直接使用类方法即可。
当然,并不是一定要使用工厂类,使用工厂函数也是可以的,但为了方便扩展,一般都会使用工厂类。
一句话总结:工厂模式就是动态创建实例