在我正在学习的一门课程中,一个PizzaStore
使用SimplePizzaFactory
类处理具体的比萨饼实例化,描述如下:
在本课程中,通过介绍需要为PizzaStore提供额外级别的特殊性以及提供相同类型的Pizza(Viggie、Cheese等)但以NY风格和Chicago风格的能力来介绍factory方法模式,因此我们有了一组新的子类(NYSTYLEVIGGEIPIZA,NYStyleCheesePizza,…芝加哥风格VIGGEIPIZA,芝加哥风格CHEESEPIZZA,…)
讲师介绍的解决方案是使用工厂方法模式,如下所示:
(统一建模语言)
用python重新编写的代码:
# Pizzas Subclasses are defined elsewhere
from abc import ABC, abstractmethod
class PizzaStore(ABC):
@abstractmethod
def create_pizza(self):
pass
def order_pizza(self,type_of_pizza):
type_of_pizza = type_of_pizza.lower()
pizza = self.create_pizza(type_of_pizza)
pizza.prepare()
pizza.bake()
pizza.box()
return pizza
class NYPizzaStore(PizzaStore):
def create_pizza(self, type_of_pizza):
if type_of_pizza == "cheese":
pizza = NYStyleCheesePizza()
elif type_of_pizza == "pepperoni":
pizza = NYStylePepperoniPizza()
elif type_of_pizza == "clam":
pizza = NYStyleClamPizza()
elif type_of_pizza == "viggie":
pizza = NYStyleViggiePizza()
else:
raise Exception("You need to specify a type of NY pizza.")
return pizza
class ChicagoPizzaStore(PizzaStore):
def create_pizza(self,type_of_pizza):
if type_of_pizza == "cheese":
pizza = ChicagoStyleCheesePizza()
elif type_of_pizza == "pepperoni":
pizza = ChicagoStylePepperoniPizza()
elif type_of_pizza == "clam":
pizza = ChicagoStyleClamPizza()
elif type_of_pizza == "viggie":
pizza = ChicagoStyleViggiePizza()
else:
raise Exception("You need to specify a type of NY pizza.")
return pizza
# ===== Driver Code =====
# NY store
ny_pizza_store = NYPizzaStore()
ny_pizza_store.order_pizza("Cheese")
ny_pizza_store.order_pizza("Pepperoni")
print()
# Chicago store
chicago_pizza_store = ChicagoPizzaStore()
chicago_pizza_store.order_pizza("Cheese")
chicago_pizza_store.order_pizza("Pepperoni")
在跳转到工厂方法之前,我尝试了以下设计,我保持了PizzaStore的原样,并用两个新类替换了SimpleFactoryPizza
:NYPizzaFactory
和ChicagoPizzaFactory
用python重新编写的代码:
class NYPizzaFactory():
def create_pizza(self,type_of_pizza):
if type_of_pizza == "cheese":
pizza = NYStyleCheesePizza()
elif type_of_pizza == "pepperoni":
pizza = NYStylePepperoniPizza()
elif type_of_pizza == "clam":
pizza = NYStyleClamPizza()
elif type_of_pizza == "viggie":
pizza = NYStyleViggiePizza()
else:
raise Exception("You need to specify a type of NY pizza.")
return pizza
class ChicagoPizzaFactory():
def create_pizza(self,type_of_pizza):
if type_of_pizza == "cheese":
pizza = ChicagoStyleCheesePizza()
elif type_of_pizza == "pepperoni":
pizza = ChicagoStylePepperoniPizza()
elif type_of_pizza == "clam":
pizza = ChicagoStyleClamPizza()
elif type_of_pizza == "viggie":
pizza = ChicagoStyleViggiePizza()
else:
raise Exception("You need to specify a type of NY pizza.")
return pizza
# PizzaStore is the same as before
class PizzaStore:
def __init__(self, pizza_factory_obj):
self.pizza_factory_obj = pizza_factory_obj
def order_pizza(self,type_of_pizza):
type_of_pizza = type_of_pizza.lower()
pizza = self.pizza_factory_obj.create_pizza(type_of_pizza)
pizza.prepare()
pizza.bake()
pizza.box()
return pizza
# ===== Driver Code ======
# NY Store
ny_pizza_factory = NYPizzaFactory()
ny_pizza_store = PizzaStore(ny_pizza_factory)
ny_pizza_store.order_pizza("Cheese")
print()
ny_pizza_store.order_pizza("Pepperoni")
print()
# Chicago Store
chicago_pizza_factory = ChicagoPizzaFactory()
chicago_pizza_store = PizzaStore(chicago_pizza_factory)
chicago_pizza_store.order_pizza("Cheese")
print()
chicago_pizza_store.order_pizza("Pepperoni")
我知道工厂方法允许类将实例化延迟到其子类,其中这些子类将包括“工厂方法”的实现
问题1:
问题2:
工厂方法结构由以下UML概括:(来自课程材料)
在《设计模式:可重用面向对象软件的元素》一书中,工厂方法模式的结构通过以下UML描述:
您最近描述的模式是抽象工厂模式;有几个工厂实现继承自同一个抽象工厂。在回答问题1时,这当然是工厂模式的一个变体
对于问题2,聚合与依赖关系实际上是一个风格问题。GoF对依赖性的使用(逻辑上)比聚合弱(即工厂依赖产品是比工厂聚合产品弱的概念)。两者都能传达信息,即两者都有效
就个人而言,我更喜欢依赖性,因为我不认为工厂实际上聚合了产品。对于聚合来说,想象一辆汽车聚合车轮。这与工厂和产品之间的关系并不是一个平行的概念。一旦产品被创造出来,工厂就与之无关了。继续这个例子,一旦一家汽车制造厂制造了一辆汽车,汽车就会离开工厂,再也不会回来,因此很难说汽车是制造它的工厂的一部分。然而,这是我的看法
我认为课程材料图表中的聚合是错误的。客户机将聚合(抽象)工厂,而不是相反,同样,工厂将聚合产品。我也不完全清楚为什么客户机不会直接引用产品,因为工厂中的关键是抽象对象的创建,而不是使用
Q1:您的实现是一个工厂吗
工厂方法模式旨在
您的设计和重新实现正是这样做的,并且是工厂
更详细的参数
在重新编写的解决方案中,根据图表,
PizzaStore
是某种上下文,可以使用NYPizzaFactory
或ChicagoPizzaFactory
或两者兼用。您的代码比UML更清晰,因为您在构建时将工厂注入到存储中你们的工厂似乎都是生产产品实例的具体创造者。每个混凝土创造者都会制作一套不同的混凝土比萨饼。单独来看,您的每个
XxxPizzaFactory
似乎对应于一个混凝土工厂,该FactoryMethod()
被称为create_pizza()
图和代码中唯一缺少的是保证工厂是可互换的,允许它们从更一般的
PizzaFactory
继承。幸运的是,Python的动态类型可以处理缺少相同基类的情况。但出于维护目的,使用UML和Python更好地构造具有显式子类化的类工厂还是抽象工厂?
每个具体工厂都可以创建不同类型的
Pizza
这一事实是被称为“参数化工厂方法”GoF的模式的变体,第110页)。因此,它确实是工厂模式,只是create_pizza()
接受一个参数,该参数指定要实例化的具体比萨饼这不是一个抽象工厂,因为抽象工厂旨在创建相关或从属产品的系列。家族中的每种产品都有其特定的工厂方法。如果您有几个create方法,比如
create_pizza(), create_dessert(), create_wine()
,那么这里就是这种情况。这里的情况并非如此,因为每个工厂只生产一种产品问题2:聚合还是依赖
首先,GoF不使用UML(参见GoF,第363页)。本书撰写时,UML尚未正式出版:
有趣的是,OMT、Booch和Objectory是三种主要的OO符号,它们被合并以创建UML
从UML的角度来看
ConcreteCreator
和ConcreteProduct
之间的关系是^{Creator
和Product
之间也应该存在«create»
依赖关系Factory
和Product
之间不应该有聚合,也不应该有关联(除非产品会跟踪创建它的工厂,或者工厂会保留它创建的所有产品的列表)关于side of the agregation有一个问题:您可以在
Client
和Factory
之间使用聚合,但是在客户端使用菱形。尽管如此,虽然从根本上讲这并不是错误的,但是simple association更能代表这两个类之间的关系其他信息:
PS:我使用了GoF来指代“设计模式:可重用面向对象软件的元素”
相关问题 更多 >
编程相关推荐