Post

设计模式系列-工厂模式

工厂模式,是创建型设计模式,提供了一种创建对象的方式。这种设计模式的主要目的是对客户端不暴露创建逻辑,并通过统一的接口指向新创建的对象。

简单工厂模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Book(object):
    @abstractmethod
    def publish(self):
        pass

class TechnicalBooks(Book):
    def publish(self):
        return "Python-Book"

class LiteraryBooks(Book):
    def publish(self):
        return "Black Hole Book"

# 现在假设我们有各种类型的书,那么使用者就必须自己实例化每个类并调用publish方法。这将实现细节暴露了出来,且当类变多时很麻烦
it_books = TechnicalBooks()
ly_books = LiteraryBooks()

这时我们就可以构造一个”简单工厂”把所有实例化的过程封装在里面,把真正实例的类隐藏起来

1
2
3
4
5
6
7
8
9
10
11
12
class SimpleFactory(object):
    """简单工厂"""

    @staticmethod
    def publish_book(name):
        if name == 'technical':
            return TechnicalBooks()
        elif name == 'literary':
            return LiteraryBooks()

it_books2 = SimpleFactory.publish_book('technical')
ly_books2 = SimpleFactory.publish_book('literary')

适用场景:

  • 工厂类负责创建的对象比较少:由于创建的对象较少,不会造成工厂方法中的业务逻辑太过复杂。
  • 客户端只知道传入工厂类的参数,对于如何创建对象不关心:客户端既不需要关心创建细节,甚至连类名都不需要记住,只需要知道类型所对应的参数。

工厂方法模式

但是,上面这张简单工厂模式不符合开闭原则。如果我们想要新增一种类型的书时,就必须要改变SimpleFactory中的if判断结构。因此出现了工厂方法模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import abc
# 真正进行实例化的类
class TechnicalBooks(object):
    def publish(self):
        return "Python-Book"


class LiteraryBooks(object):
    def publish(self):
        return "Black Hole Book"


# 抽象工厂:先定义抽象类,然后每种类型的书籍都有自己对于的工厂
class AbstractFactory(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def publish_book(self):
        pass

class TechnicalFactory(AbstractFactory):
    """技术书籍工厂"""
    def publish_book(self):
        return TechnicalBooks()


class LiteraryFactory(AbstractFactory):
    """文学书籍工厂"""
    def publish_book(self):
        return LiteraryBooks()


it_books2 = TechnicalFactory().publish_book()
ly_books2 = LiteraryFactory().publish_book()

这样每个工厂就只负责生产自己的产品,避免了在新增产品时需要修改工厂的代码,遵循了”开闭原则”,如果需要新增产品时,只需要增加相应的工厂即可。 适用场景:

  • 当系统中拥有的子类很多,并且以后可能还需要不断拓展增加不同的子类时。
  • 当设计系统时,还不能明确具体有哪些类时。
  • 在工厂方法中,使用者不需要知道具体的产品类名,只需要知道其对应的工厂即可。

抽象工厂

在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import abc
# 印刷书籍
class PrintingTechnicalBooks(object):
    """印刷技术书籍"""

    def printing(self):
        return "Print-Python-Book"


class PrintingLiteraryBooks(object):
    """印刷文学书籍"""

    def printing(self):
        return "Print Black Hole Book"


# 出版书籍
class TechnicalBooks(object):
    """出版技术书籍"""

    def publish(self):
        return "Python-Book"


class LiteraryBooks(object):
    """出版文学书籍"""

    def publish(self):
        return "Black Hole Book"


# 抽象工厂:先定义抽象类,然后每种类型的书籍都有自己对于的工厂
class AbstractFactory(metaclass=abc.ABCMeta):
    """抽象工厂"""

    @abc.abstractmethod
    def print_book(self):
        pass

    @abc.abstractmethod
    def publish_book(self):
        pass


class TechnicalFactory(AbstractFactory):
    """技术书籍工厂"""

    def print_book(self):
        return PrintingTechnicalBooks()

    def publish_book(self):
        return TechnicalBooks()


class LiteraryFactory(AbstractFactory):
    """文学书籍工厂"""

    def print_book(self):
        return PrintingLiteraryBooks()

    def publish_book(self):
        return LiteraryBooks()


# 实例化工厂对象
it = TechnicalFactory()
ly = LiteraryFactory()

# 印刷书籍
it_print = it.print_book()
ly_print = ly.print_book()
# 出版书籍
it_publish = it.publish_book()
ly_publish = ly.publish_book()

参考: 图解设计模式 https://design-patterns.readthedocs.io/zh_CN/latest/creational_patterns/factory_method.html 设计模式之工厂模式 https://www.cnblogs.com/yssjun/p/11102162.html

This post is licensed under CC BY 4.0 by the author.