什么是工厂模式 -- factory pattern
工厂模式
,也成为简单工厂模式或者静态工厂模式
它属于创建型模式,它提供了一种创建对象的最佳方式.在工厂模式中,我们在创建对象的时候,不会对客户端暴露创建逻辑,所谓的创建逻辑
就是指必须要知道创建函数的构造函数的逻辑组成,才能创建对象
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
student=Student('张三',23)
在上面的例子中,要想创建一个学生对象,我就必须要知道学生的 姓名 、年龄 这两项基本信息才能创建,这两个信息,就是所谓的创建逻辑,在实际中,可能知道的信息还要更多我才能创建一个实例,因为在同龄人中 姓名也相同的大有人在,我还需要知道他多高,性别、喜欢什么、籍贯等等才能完全创建一个学生实例。那有没有办法在不知道学生姓名和这些信息的情况下创建一个学生实例呢?这就是工厂模式要做的事情。
所谓”工厂模式“就是专门提供一个”工厂类“去创建对象,我只需要告诉这个工厂我需要什么,它就会返回给我一个相对应的对象。
说的更通俗一点,就是专门创建类型的实例的工厂(类)
使用场景:
您需要一辆汽车,可以直接从工厂里面提货,而不用去管这辆汽车是怎么做出来的,以及这个汽车里面的具体实现。
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
总结:
如果要创建一系列复杂对象,需要提供更多的信息,或者是我们要隐藏创建对象的时候的逻辑代码,就需要使用工厂模式.
优点:
一个调用者想创建一个对象,只要知道其名称就可以了,不需要知道其他详细信息。 2、作为调用者而言,屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:
当有新的类型要加入到系统中时,必须修改工厂类,加入必要的处理逻辑,这违背了“开闭原则”。在简单工厂模式中,所有的产品都是由同一个工厂创建,工厂类职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度高,严重影响了系统的灵活性和扩展性,而工厂方法模式则可以很好地解决这一问题。(工厂方法模式和工厂模式是有区别的哦)
使用实例:
1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。 2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。 3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。
简单工厂模式的代码实现:
比如我需要创建很多的图形对象,这些图形包括三角形、圆、矩形、椭圆等等,当然我们可以使用每一个类型的构造函数去创建。但是我们不这样做,我们只需要专门创建一个“工厂类”,然后在需要创建某个实例的时候告诉它我需要什么类,就可以啦,如下代码所示:
第一步: 首先是创建四个具体的类,用来创建具体的对象.
第二步: 创建一个工厂类,根据名字来创建具体的对象
# encoding:utf-8
__author__ = 'Fioman'
__time__ = '2019/3/6 16:58'
import math
# 简单工厂模式的四个具体的创建类
class Circle(object):
# 计算面积
def area(self, radius):
return math.pi * radius * radius
class Rectangle(object):
# 计算面积
def area(self, longth, width):
return 2 * longth * width
class Triangle(object):
# 计算面积
def area(self, baselong, height):
return baselong * height / 2
class Ellipse:
def area(self, long_a, long_b):
return math.pi * long_a * long_b
# 创建一个工厂类,专门用来创建具体的对象
class ShapeFactory(object):
def create_shape(self, name):
if name == 'Circle':
return Circle()
elif name == 'Rectangle':
return Rectangle()
elif name == 'Triangle':
return Triangle()
elif name == 'Ellipse':
return Ellipse()
else:
return None
if __name__ == '__main__':
factory = ShapeFactory()
circle = factory.create_shape('Circle')
circle_area = circle.area(2)
print('这是一个圆,它的面积是:{}'.format(circle_area))
# 获取矩形对象
rect = factory.create_shape('Rectangle')
rect_area = rect.area(2, 4)
print('这是一个矩形,它的面积是:{}'.format(rect_area))
# 获取三角形对象
triangle = factory.create_shape('Triangle')
triangle_area = triangle.area(2, 4)
print('它是一三角形,它的面积是:{}'.format(triangle_area))
# 获取椭圆形对象
ellipse = factory.create_shape('Ellipse')
ellipse_area = ellipse.area(4, 8)
print('它是一个椭圆形,它的面积是:{}'.format(ellipse_area))
从上面可以看出,我们在创建某一个图形类的时候,根本不关心这个类的构造函数到底是什么,甚至它都没有自定义的构造函数,这并不影响,我们只需要告诉工厂,你给我创建一个什么类即可,除了这点信息以外,不需要知道任何的额外信息,这就是所谓的“隐藏创建类的代码逻辑” 。
但是上面的方法依然有一个缺点:
简单工厂模式实现了生成产品类的代码跟客户端代码分离,在工厂类中你可以添加所需的生成产品的逻辑代码,但是问题来了,优秀的java代码是符合“开放-封闭”原则的,也就是说对扩展开发,对修改关闭,如果你要加一个产品类C,你就要修改工厂类里面的生成产品的代码,在这里你就要增加if-else判断。对于这个问题,我们的工厂方法模式就可以解决这个问题。
简单工厂模式,违背开放闭合原则,每次需要添加新对象的时候,都要修改工厂函数,这样是不合理的.所以引入了工厂方法模式.
工厂方法模式 Factory_Method Pattern
概念解析:
工厂方法模式是对简单工厂模式的一个延伸,所以他们诞生的背景和所解决的问题是差不多的.而工厂方法模式解决了简单工厂模式违背了开放封闭原则.
我们知道,工厂模式,只提供了一个工厂类,这个工厂类重新定义了一个方法去创建每一个类型,然后根据名字,可以获取自己想要的类型.
但是工厂方法模式
则提供了一系列的工厂创建类,即每一种类型对应一种工厂,但是这些工厂又遵循一个工厂接口,只不过是重新实现了接口中的创建方法,如下图所示:
工厂方法模式的Python代码实现
# encoding:utf-8
__author__ = 'Fioman'
__time__ = '2019/3/6 16:58'
import math
# 简单工厂模式的四个具体的创建类
class Circle(object):
# 计算面积
def area(self, radius):
return math.pi * radius * radius
class Rectangle(object):
# 计算面积
def area(self, longth, width):
return 2 * longth * width
class Triangle(object):
# 计算面积
def area(self, baselong, height):
return baselong * height / 2
class Ellipse:
def area(self, long_a, long_b):
return math.pi * long_a * long_b
# 定义创建对象的工厂接口,因为python中并没有接口的概念,所以,这里打算通过'类继承'来实现
class IFactory(object):
def create_shape(self,name): # 定义接口的方法,只提供方法的声明,不提供方法的实现
pass
class CircleFactory(IFactory):
def create_shape(self,name): # 重写接口中的方法
if name == 'Circle':
return Circle()
class RectangleFactory(IFactory):
def create_shape(self,name):
if name == 'Rectangle':
return Rectangle()
class TriangleFactory(IFactory):
def create_shape(self,name):
if name == 'Triangle':
return Triangle()
class EllipseFactory(IFactory):
def create_shape(self,name):
if name == 'Ellipse':
return Ellipse()
if __name__ == '__main__':
circle = CircleFactory().create_shape('Circle')
circle_area = circle.area(2)
print('这是一个圆,它的面积是:{}'.format(circle_area))
# 获取矩形对象
rect = RectangleFactory().create_shape('Rectangle')
rect_area = rect.area(2, 4)
print('这是一个矩形,它的面积是:{}'.format(rect_area))
# 获取三角形对象
triangle = TriangleFactory().create_shape('Triangle')
triangle_area = triangle.area(2, 4)
print('它是一三角形,它的面积是:{}'.format(triangle_area))
# 获取椭圆形对象
ellipse = EllipseFactory.create_shape('Ellipse')
ellipse_area = ellipse.area(4, 8)
print('它是一个椭圆形,它的面积是:{}'.format(ellipse_area))
工厂方法的优缺点
优点:
(1)工厂方法模式具有简单工厂模式的优点,那就是用户不需要知道创建某一个类型的细节,即隐藏了代码的“创建逻辑”
(2)在增加一个新的图形类的时候,比如再加一个平行四边形,我不用去修改代码,只需要增加对应的平行四边形工厂就好,完全符合开放——封闭性原则! 自己添加一个平行四边形工厂类,只要让其实现抽象的工厂接口就可以啦,即只需要自己编写拓展模块,而不用更改原来的代码。这完美的体现了多态性!
缺点:
(1)在增加新的一个类型时,也必须增加相应的新的工厂类,会带来额外的开销,会导致很多的工厂类,影响代码的简洁性。
网友评论