検索ガイド -Search Guide-

単語と単語を空白で区切ることで AND 検索になります。
例: python デコレータ ('python' と 'デコレータ' 両方を含む記事を検索します)
単語の前に '-' を付けることで NOT 検索になります。
例: python -デコレータ ('python' は含むが 'デコレータ' は含まない記事を検索します)
" (ダブルクオート) で語句を囲むことで 完全一致検索になります。
例: "python data" 実装 ('python data' と '実装' 両方を含む記事を検索します。'python data 実装' の検索とは異なります。)
当サイトのドメイン名は " getwebtips.net " です。
トップレベルドメインは .net であり、他の .com / .shop といったトップレベルドメインのサイトとは一切関係ありません。
practical_python_design_patterns

Practical Python Design Patterns - Python で学ぶデザインパターン: The Factory Pattern - Part. 3 「ファクトリーメソッド」の巻 投稿一覧へ戻る

Published 2022年5月25日21:08 by T.Tsuyoshi

SUPPORT UKRAINE

- Your indifference to the act of cruelty can thrive rogue nations like Russia -

The Factory Method
(ファクトリーメソッド)

文字列を引数としてあるメソッドを呼び出し、返り値として新しいオブジェクトを受け取る場合、そのメソッドは実質的にファクトリーメソッドである、と見なすことができます。受け取るオブジェクトの種類は引数として渡した文字列により左右されます。
この実装パターンを採用すると、開発するソフトウェアに対して新しい機能の追加を非常に簡単に行えるようになります。新規機能を提供するクラスを定義し、そのクラスを識別する文字列をファクトリーメソッドが処理できるようにすれば、そのクラスのオブジェクトを取得できるようになるからです。
ファクトリーメソッドの簡単な実装例を見てみましょう:
import pygame


class Shape:
def __init__(self, x, y):
self.x = x
self.y = y

def draw(self):
raise NotImplementedError()

def move(self, direction):
if direction == 'up':
self.y -= 4
elif direction == 'down':
self.y += 4
elif direction == 'left':
self.x -= 4
elif direction == 'right':
self.x += 4

@staticmethod
def factory(type):
if type == 'circle':
return Circle(100, 100)
if type == 'square':
return Square(100, 100)

assert 0, '定義されていない図形がリクエストされました: ' + type


class Square(Shape):
def draw(self):
pygame.draw.rect(
screen,
(255, 255, 0),
pygame.Rect(self.x, self.y, 20, 20)
)


class Circle(Shape):
def draw(self):
pygame.draw.circle(
screen,
(0, 255, 255),
(self.x, self.y),
10
)

if __name__ == '__main__':
window_dimensions = 800, 600
screen = pygame.display.set_mode(window_dimensions)

obj = Shape.factory('square')
player_quits = False

while not player_quits:
for event in pygame.event.get():
if event.type == pygame.QUIT:
player_quits = True

pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]: obj.move('up')
if pressed[pygame.K_DOWN]: obj.move('down')
if pressed[pygame.K_LEFT]: obj.move('left')
if pressed[pygame.K_RIGHT]: obj.move('right')
screen.fill((0, 0, 0))
obj.draw()

pygame.display.flip()
この実装であれば、描画する図形を矩形から円に、もしくは、他の図形や好きな画像に変更するのがいかにたやすいか分かりますよね?
ファクトリーパターンの愛好者の中には、全てのコンストラクタは private もしくは protected であるべきだ、と主張する人もいます。それは、クラスのユーザーにとって、ファクトリメソッドが返すオブジェクトが新たに作成されたものなのか、それとも、再利用されているものなのかは重要ではない、という理由からです。要は、オブジェクト要求のリクエストと実際のオブジェクト作成を切り離して考える、ということですね。
こうした考え方を「そうしなければならないこと」と捉えるべきではありません。しかし自分のプロジェクトで試してみて、その結果を確かめてみるのは無駄ではないでしょう。そして、ファクトリーメソッド、ひいては、ファクトリーパターンの使い勝手が良いようであれば、その有用性を自分のプロジェクトに活かすのは自由なはずです。
ゲームスクリーン上に新たな図形を描画するために新しいクラスを作成した場合、やるべき必要があることは factory() メソッドに変更を加えることだけです。

この投稿をメールでシェアする

0 comments

コメントはまだありません。

コメントを追加する(不適切と思われるコメントは削除する場合があります)