设计模式 - 工厂模式

本贴最后更新于 922 天前,其中的信息可能已经时移世易

工厂模式

image.png

使用场景

工厂模式是对一种实例化对象方法的一种非常形象的描述。它把一个类比作一个工厂,而类的对象就是工厂生产出来的产品。通过类实例化对象就好比工厂生产出产品。使用产品的人不在乎产品是如何生产出来的。

从软件开发的角度来说,工厂模式可以有效的降低模块之间的耦合度。

创建需要的对象而不必关心实例化的过程,用户只需要通过固定的接口而不是直接调用具体类的实例化方法来创建对象,隐藏了实例创建过程的复杂度,解耦了创建实例代码和使用实例代码。

工厂模式又分为简单工厂模式,工厂方法模式和抽象工厂模式。

代码实现

简单工厂

系统中需要连接不同的数据库,不同的数据库连接实例化不同的类。

class Mysql:
    """mysql数据库"""

    def connect(self):
        return 'mysql'


class Oracle:
    """oracle数据库"""

    def connect(self):
        return 'oracle'

# 如果直接实例化,就直接暴露了真正的类
mysql_connect = Mysql()
oracle_connect = Oracle()

# 这时就可以创建一个简单工厂类,把创建过程进行封装,把真正的类隐藏起来
class DbFactory:
    """数据库简单工厂"""
    @staticmethod
    def factory(type_):
        if type_ == 'mysql':
            return Mysql()
        elif type_ == 'oracle':
            return Oracle()

mysql_connect = DbFactory.factory('mysql')
oracle_connect = DbFactory.factory('oracle')

采用简单工厂的优点时可以使用户根据参数获得对应的类实力,避免直接实例化类,降低了耦合性。缺点是,违背了开闭原则(OCP),如果增加新的类型,则需要修改工厂。

工厂方法

为了解决简单工厂的缺陷,现在再在工厂类抽象一层。先创建一个工厂抽象类,然后不同的数据库创建不同的工厂。

import abc


class Mysql:
    """mysql数据库"""

    def connect(self):
        return 'mysql'


class Oracle:
    """oracle数据库"""

    def connect(self):
        return 'oracle'


# 定义一个工厂抽象类,然后每种数据库都有对应的工厂类
class AbstractFactory(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def create(self):
        raise NotImplementedError()


# mysql工厂类
class MysqlFactory(AbstractFactory):

    def create(self):
        return Mysql()


# oracle工厂类
class OracleFactory(AbstractFactory):
    def create(self):
        return Oracle()


# 分别通过各自的工厂类实例化
mysql = MysqlFactory().create()
oracle = OracleFactory().create()

然后通过不同的工厂类创建不同的数据库对象。当有新的数据库需要添加时,只需要添加新的数据库类和对应的工厂类即可,而不需要修改原来的代码。这就是工厂方法。工厂方法相比简单工厂更加的复合开闭原则,但代码的复杂度有所增加。

抽象工厂

现在有了新的需求,系统中数据库要求进行读写分离,每种数据库分为读数据库和写数据库(当然可以通过其他的办法实现,这里只是为了讲清楚抽象工厂)。如果按照工厂方法,我们就需要创建新的工厂类,那么能否让一个工厂创建同一类数据库的多种操作连接呢?

import abc


class MysqlOnlyRead:
    """mysql数据库-只读"""

    def connect(self):
        return 'mysql-只读'


class MysqlOnlyWrite:
    """mysql数据库-只写"""

    def connect(self):
        return 'mysql-只写'


class OracleOnlyRead:
    """oracle数据库-只读"""

    def connect(self):
        return 'oracle-只读'


class OracleOnlyWrite:
    """oracle数据库-只写"""

    def connect(self):
        return 'oracle-只写'


# 抽象工厂
class AbstractFactory(metaclass=abc.ABCMeta):

    @abc.abstractmethod
    def create_read(self):
        raise NotImplementedError()

    @abc.abstractmethod
    def create_write(self):
        raise NotImplementedError()


# mysql工厂类
class MysqlFactory(AbstractFactory):

    def create_read(self):
        return MysqlOnlyRead()

    def create_write(self):
        return MysqlOnlyWrite()


# oracle工厂类
class OracleFactory(AbstractFactory):

    def create_read(self):
        return OracleOnlyRead()

    def create_write(self):
        return OracleOnlyWrite()


# 通过调用工厂的不同方法创建不同的对象
mysql_read = MysqlFactory().create_read()
mysql_write = MysqlFactory().create_write()
oracle_read = OracleFactory().create_read()
oracle_write = OracleFactory().create_write()

可以看到抽象工厂在工厂的方法基础上进一步的增加了新的创建方法,从而让一个工厂能够生产同一个数据库的多种操作对象。

回帖
请输入回帖内容 ...