Pythonインタビュー【9】~Pythonデザインパターン特集~第2回

3. ファクトリーモデル

ファクトリー パターンは、最も一般的に使用されるデザイン パターンの 1 つです。このタイプのデザイン パターンは、オブジェクトを作成する最適な方法を提供する創造的なパターンです。ファクトリ パターンでは、オブジェクトを作成するときに、作成ロジックをクライアントに公開せず、共通のインターフェイスを使用して新しく作成されたオブジェクトを指しますコンセプト: オブジェクト インターフェイスを作成し、そのサブクラスにどのファクトリ クラスをインスタンス化するかを決定させます。ファクトリ パターンは、クラスのインスタンス化をサブクラスに延期します。 主な解決策: 主にインターフェイスの選択の問題を解決しますいつ使用するか : 異なる条件下で異なるインスタンスを作成する場合は、明示的に計画します。


ファクトリ デザイン パターンでは、クライアントは、オブジェクトがどこから来たのか、つまり、オブジェクトの生成にどのクラスが使用されたのかを知らなくても、オブジェクトをリクエストできます。ファクトリの背後にある考え方は、オブジェクトの作成を簡素化することです。クライアント自体がインスタンス化に基づいてオブジェクトを直接作成する場合と比較して、集中機能に基づいてどのオブジェクトが作成されたかを追跡するのが簡単です。
ファクトリは、オブジェクトを作成するコードを、オブジェクトを使用するコードから分離することで、アプリケーションのメンテナンスの複雑さを軽減できます。
ファクトリ メソッドがオブジェクトを作成するとき、特定のクラスに結合/バインドされることはなく、関数を呼び出すことで必要なものについて部分的な情報が提供されるだけです。これは、この関数を使用するコードを変更することなく、この関数を変更する方が簡単であることを意味します。

ファクトリには通常、次の 3 つの形式があります。
(1) シンプル ファクトリ: シンプル ファクトリは実際のデザイン パターンではなく、別のクラスを渡すプログラミングの習慣に似ています。インスタンスでは、通常、このクラスには、異なる入力パラメータに従って異なるオブジェクトを返す静的メソッドが含まれています。
(2) ファクトリ メソッド: ファクトリ モード パターンは、オブジェクトを作成するためのインターフェイスを定義し、サブクラスにどのインターフェイスを決定させるかインスタンス化するクラス。このパターンでは、クラスのインスタンス化をそのサブクラスに延期します。
(3) 抽象ファクトリ: 一連の関連オブジェクトを作成するために使用されるファクトリ メソッドのセットです。

1. 単純なファクトリ: [静的メソッド]

1 つのクラスを外部インターフェイスとして使用し、さまざまなパラメーターに基づいてさまざまなクラスをインスタンス化することを選択します。

1. """
 2. 两个产品(两种类型的书)
 3. """
 4. class TechnicalBooks(object):
 5.     """技术书籍"""

 7.     def publish(self):
 8.         return "Python-Book"
 9.  
10. class LiteraryBooks(object):
11.     """文学书籍"""
12.  
13.     def publish(self):
14.         return "Black Hole Book"
15.  
16. # 现在我们有两种类型的书,分别是TechnicalBooks和LiteraryBooks的书
17. # 按照我们平常的方法来实例化的话,此时创建对象时是会对客户端暴露真正创建的类
18. it_books = TechnicalBooks()
19. ly_books = LiteraryBooks()
20.  
21. # 这时我们就可以构造一个"简单工厂"把所有实例化的过程封装在里面,把真正实例的类隐藏起来
22. class SimpleFactory(object):
23.     """简单工厂"""
24.     @staticmethod
25.     def publish_book(name):
26.         if name == 'technical':
27.             return TechnicalBooks()
28.         elif name == 'literary':
29.             return LiteraryBooks()
30.  # 通过类调用:class_name.fun_name()
31. it_books2 = SimpleFactory.publish_book('technical')
32. ly_books2 = SimpleFactory.publish_book('literary')

単純なファクトリの利点は、さまざまなクラスのインスタンス化を 1 つの「ファクトリ」に統合することです。つまり、実際に作成されたクラスを外部に公開せず、また、統合されたインターフェイスも提供します。外の世界。ただし、シンプルモードにはsoilの「開閉原理」に反するというデメリットがあり、追加する場合はブックを追加する必要があり、さらにシンプルファクトリSimpleFactoryのソースコードを修正する必要があります。
単純なファクトリーの使用シナリオ:

  • 特定のクラスがいくつあるかは決定されており、追加のケースでは使用されません。

2.工場出荷時の方法

私たちは上記の単純なファクトリーを知っています。いくつかの新しいタイプを追加すると、ソフトウェア設計における開始と終了の原則に違反します。しかし、新しいカテゴリを拡張するときに、元のコードを変更しないことを望んでいます。現時点では、 SimpleFactory をさまざまなファクトリに抽象化し、各ファクトリが独自の製品を生成する、これがファクトリ メソッドです。

1. """
 2. 两个产品(两种类型的书)
 3. """
 4. from abc import ABC, abstractmethod
 5. # 真正进行实例化的类
 6. class TechnicalBooks(object):
 7.     """技术书籍"""
 8.     def publish(self):
 9.         return "Python-Book"
10.  
11. class LiteraryBooks(object):
12.     """文学书籍"""
13.     def publish(self):
14.         return "Black Hole Book"
15.  
16. # 抽象工厂:先定义抽象类,然后每种类型的书籍都有自己对于的工厂
17. class AbstractFactory(metaclass=abc.ABCMeta):
18.     """抽象工厂"""
19.     @abstractmethod
20.     def publish_book(self):
21.         pass
22.  
23. class TechnicalFactory(AbstractFactory):
24.     """技术书籍工厂"""
25. 
26.     def publish_book(self):
27.         return TechnicalBooks()
28.  
29. class LiteraryFactory(AbstractFactory):
30.     """文学书籍工厂"""
31.  
32.     def publish_book(self):
33.         return LiteraryBooks()
34.  
35. it_books2 = TechnicalFactory().publish_book()   
36. ly_books2 = LiteraryFactory().publish_book()    
	# 如果通过类调用是不带括号的
	# 该代码带括号等价于先创建实例然后通过实例调用方法

このように、各工場は独自の製品の生産のみを担当するため、新しい製品を追加するときに工場コードを変更する必要がなくなります。「開閉原則」に従います。製品の場合は、対応する工場を追加するだけです。
たとえば、新しい種類の本を追加する場合は、NovelBooks クラスと NovelFactory クラスを追加するだけです。
ファクトリ メソッドの使用シナリオ:

  • システム内に多数のサブカテゴリがあり、将来的にさまざまなサブカテゴリを継続的に拡張および追加する必要がある場合。
  • システムを設計するとき、どのようなクラスがあるのか​​は明確ではありません。

ファクトリ メソッドでは、ユーザーは特定の製品クラス名を知る必要はなく、対応するファクトリだけを知る必要があります。

3. 抽象ファクトリー

ファクトリー メソッドは「オープンとクローズの原則」の問題を解決しますが、本を出版する前に印刷などの他の手順が必要です。各ステップに対応するファクトリ クラスを作成する必要がある場合は、多くのクラスを作成する必要があります。この問題を解決するには、ファクトリが同じタイプの複数の製品または複数のアクション (ステップ) を生産できるようにする抽象ファクトリ クラスが必要です。これは抽象的な工場です。

1. """
 2. 两个产品(两种类型的书)
 3. """
 4. import abc
 5.  
 6. # 印刷书籍
 7. class PrintingTechnicalBooks(object):
 8.     """印刷技术书籍"""
 9.     def printing(self):
10.         return "Print-Python-Book"
11.  
12. class PrintingLiteraryBooks(object):
13.     """印刷文学书籍"""
14.     def printing(self):
15.         return "Print Black Hole Book"
16.  
17. # 出版书籍
18. class TechnicalBooks(object):
19.     """出版技术书籍"""
20.     def publish(self):
21.         return "Python-Book"
22.  
23. class LiteraryBooks(object):
24.     """出版文学书籍"""
25.     def publish(self):
26.         return "Black Hole Book"
27.  
28. # 抽象工厂:先定义抽象类,然后每种类型的书籍都有自己对于的工厂
29. class AbstractFactory(metaclass=abc.ABCMeta):
30.     """抽象工厂"""
31.  
32.     @abc.abstractmethod
33.     def print_book(self):
34.         pass
35.  
36.     @abc.abstractmethod
37.     def publish_book(self):
38.         pass
39.  
40. class TechnicalFactory(AbstractFactory):
41.     """技术书籍工厂"""
42.  
43.     def print_book(self):
44.         return PrintingTechnicalBooks()
45.  
46.     def publish_book(self):
47.         return TechnicalBooks()
48.  
49. class LiteraryFactory(AbstractFactory):
50.     """文学书籍工厂"""
51.     def print_book(self):
52.         return PrintingLiteraryBooks()
53.  
54.     def publish_book(self):
55.         return LiteraryBooks()
56.  
58. # 实例化工厂对象
59. it = TechnicalFactory()
60. ly = LiteraryFactory()
61.  
62. # 印刷书籍
63. it_print = it.print_book()
64. ly_print = ly.print_book()
65. # 出版书籍
66. it_publish = it.publish_book()
67. ly_publish = ly.publish_book()

  • 抽象ファクトリ パターンとファクトリ メソッド パターンの違いは次のとおりです。
    • 抽象ファクトリ内のファクトリ オブジェクトは、複数の異なる製品オブジェクトの作成を担当できます。
  • 抽象ファクトリーの使用シナリオ:
    • 複数の製品(ステップ)がまとめられて製品ファミリーを形成する場合
    • 製品ファミリに対応する場合、実装ではなくインターフェイスのみを表示したい場合。

4. ビルダーモード

複雑なオブジェクトの構築をその表現から分離し、同じ構築プロセスで異なる表現を作成できるようにします。ビルダー パターンはすべての詳細をサブクラスに残します。。条件:キャラクターを描くには、人の左手、右手、左足、右足と胴体を描き、痩せた男性と太った男性を描く必要があります。

1. デザインパターンを使用しない

1. if __name__=='__name__':
 2.     print '画左手'
 3.     print '画右手'
 4.     print '画左脚'
 5.     print '画右脚'
 6.     print '画胖身体'
 7.  
 8.     print '画左手'
 9.     print '画右手'
10.     print '画左脚'
11.     print '画右脚'
12.     print '画瘦身体'

このように書くことの欠点は、人物を描くたびに、その人物の 5 つの部分を描かなければならないことです。これらの部分の一部は再利用できるため、呼び出しがさらに面倒になり、顧客が迷惑になる可能性があります。パーツを呼び出すときにそれらの 1 つを描画するのを忘れるため、エラーが発生しやすくなります。
抽象クラス Builder を作成し、その 5 つの部分を描画するメソッドを宣言します。描画される人物のタイプごとに、Builder を継承する新しいクラスを作成します。このようにして、新しいクラスはすべてのメソッドを実装する必要があります。 Builder の機能。メソッド、ここでは主に抽​​象メソッドの特性を使用します。親クラスはいくつかの抽象メソッドを定義します。サブクラスはこれらのメソッドを実装する必要があります。実装しない場合はエラーが報告されます。ここで問題を解決します。部品が足りないという問題。ディレクター クラス Director を構築し、Builder メソッドを入力し、draw メソッドを定義し、これら 5 つの部分を描画するためのすべてのメソッド呼び出しをその中に入れます。そうすることで、呼び出しが煩雑にならないようにします。

  • Python 自体は抽象クラスやインターフェイス機構を提供していませんが、抽象クラスを実装したい場合は、abc モジュールを使用できます。 AbcモジュールはAbstract Base Classの略称です。
  • @abstractmethod によって抽象メソッドとして装飾された後は、メソッドをインスタンス化できませんが、サブクラスが基本クラスの抽象メソッドを実装していない限り、インスタンス化できます。

2. デザインパターンを使用する

1. #encodig=utf-8
 2. from abc import ABCMeta, abstractmethod
 3. class Builder():
 4.     __metaclass__ = ABCMeta
 5.     
 6.     @abstractmethod
 7.     def draw_left_arm(self):
 8.         pass
 9.
10.     @abstractmethod
11.     def draw_right_arm(self):
12.         pass
13.     
14.     @abstractmethod
15.     def draw_left_foot(self):
16.         pass
17.     
18.     @abstractmethod
19.     def draw_right_foot(self):
20.         pass
21.     
22.     @abstractmethod
23.     def draw_body(self):
24.         pass
25.     
26. class Thin(Builder): # 继承抽象类,必须实现其中定义的方法
27.     def draw_left_arm(self):
28.         print('画瘦子左手')
29.     
30.     def draw_right_arm(self):
31.         print('画瘦子右手')
32.     
33.     def draw_left_foot(self):
34.         print('画瘦子左脚')
35.     
36.     def draw_right_foot(self):
37.         print('画瘦子右脚')
38.     
39.     def draw_body(self):
40.         print('画瘦子身体')
41.         
42. class Fat(Builder): # 继承抽象类,必须实现其中定义的方法
43.     def draw_left_arm(self):
44.         print('画胖子左手')
45.     
46.     def draw_right_arm(self):
47.         print('画胖子右手')
48.     
49.     def draw_left_foot(self):
50.         print('画胖子左脚')
51.     
52.     def draw_right_foot(self):
53.         print('画胖子右脚')
54.     
55.     def draw_body(self):
56.         print('画胖子的身体')
57.         
58. class Director():
59.     def __init__(self, person):
60.         self.person = person
61.         
62.     def draw(self):
63.         self.person.draw_left_arm()
64.         self.person.draw_right_arm()
65.         self.person.draw_left_foot()
66.         self.person.draw_left_foot()
67.         self.person.draw_body()
68.         
69. if __name__ == '__main__':
70.     thin = Thin()
71.     fat = Fat()
72.     director_thin = Director(thin)
73.     director_thin.draw()
74.     director_fat = Director(fat)
75.     director_fat.draw()

ビルダー パターンは、複雑なオブジェクトの構築をその表現から分離するために使用され、同じ構築プロセスで異なる表現を作成できるようになります。

おすすめ

転載: blog.csdn.net/s1_0_2_4/article/details/134888560