返回顶部
首页 > 资讯 > 后端开发 > Python >Python中工厂方法模式有什么用
  • 792
分享到

Python中工厂方法模式有什么用

2023-06-17 13:06:59 792人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

这篇文章主要为大家展示了“python中工厂方法模式有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python中工厂方法模式有什么用”这篇文章吧。工厂方法(Factory Method)

这篇文章主要为大家展示了“python中工厂方法模式有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python中工厂方法模式有什么用”这篇文章吧。

工厂方法(Factory Method)模式又称为虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,属于类的创建型模式。在工厂方法模式中,父类负责定义创建对象的公共接口,而子类则负责生成具体的对象,这样做的目的是将类的实例化操作延迟到子类中完成,即由子类来决定究竟应该实体化哪一个类。

在简单工厂模式中,一个工厂类处于对产品类进行实例化的中心位置上,它知道每一个产品类的细节,并决定何时哪一个产品类应当被实例化。简单工厂模式的优点是能够使客户端独立于产品的创建过程,并且在系统中引入新产品时无需对客户端进行修改,缺点是当有新产品要加入到系统中时,必须对工厂类进行修改,以加入必要的处理逻辑。简单工厂模式的致命弱点就是处于核心地位的工厂类,因为一旦它无法确定要对哪个类进行实例化时,就无法使用该模式,而工厂方法模式则可以很好地避免这一问题。

考虑这样一个应用程序框架(Framework),它可以用来浏览各种格式的文档,如TXT、DOC、pdfhtml等,设计时为了让软件的体系结构能够尽可能地通用,定义了Application和Document这两个抽象父类,客户必须通过它们的子类来处理某一具体类型的文档。例如,要想利用该框架来编写一个PDF文件浏览器,必须先定义PDFApplication和PDFDocument这两个类,它们应该分别继承于Application和Document。

Application的职责是对Document进行管理,并且在需要时创建它们,比如当用户从菜单中选择Open或者New的时候,Application就要负责创建一个Document的实例。显而易见,被实例化的特定Document子类是与具体应用相关的,因此Application无法预测哪个Document的子类将被实例化,它只知道一个新的Document何时(When)被创建,但并不知道哪种(Which)具体的Document将被创建。此时若仍坚持使用简单工厂模式会出现一个非常尴尬的局面:框架必须实例化类,但它只知道不能被实例化的抽象类。

解决的办法是使用工厂方法模式,它封装了哪一个Document子类将被创建的信息,并且能够将这些信息从框架中分离出来。如图1所示,Application的子类重新定义了Application的抽象方法createDocument(),并返回某个恰当的Document子类的实例。我们称createDocument()是一个工厂方法(factory method),因为它非常形象地描述了类的实例化过程,即负责"生产"一个对象。

Python中工厂方法模式有什么用

简单说来,工厂方法模式的作用就是可以根据不同的条件生成各种类的实例,这些实例通常属于多个相似的类型,并且具有共同的父类。工厂方法模式将这些实例的创建过程封装了起来,从而简化了客户程序的编写,并改善了软件体系结构的可扩展性,使得将来能够以最小的代价加入新的子类。工厂方法这一模式适合在如下场合中运用:

◆当无法得知必须创建的对象属于哪个类的时候,或者无法得知属于哪个类的对象将被返回的时候,但前提是这些对象都符合一定的接口标准。

◆当一个类希望由它的子类来决定所创建的对象的时候,其目的是使程序的可扩展性更好,在加入其他类时更具弹性。

◆当创建对象的职责被委托给多个帮助子类(helper subclass)中的某一个,并且希望将哪个子类是代理者这一信息局部化的时候。

需要说明的是,使用工厂方法模式创建对象并不意味着一定会让代码变得更短(实事上往往更长),并且可能需要设计更多的辅助类,但它的确可以灵活地、有弹性地创建尚未确定的对象,从而简化了客户端应用程序的逻辑结构,并提高了代码的可读性和可重用性。

二、模式引入

工厂方法这一模式本身虽然并不复杂,但却是最重要的设计模式之一,无论是在COM、CORBA或是EJB中,都可以随处见到它的身影。面向对象的一个基本思想是在不同的对象间进行责权的合理分配,从本质上讲,工厂方法模式是一种用来创建对象的多态方法(polymorphic method),它在抽象父类中声明用来创建对象的方法接口,而具体子类则通过覆盖该方法将对象的创建过程局部化,包括是否实例化一个子类,以及是否对它进行初始化等等。从某种程度上说,工厂方法可以看成是构造函数的特殊化,其特殊性表现在能够用一致的方法来创建不同的对象,而不用担心当前正在对哪个类进行实例化,因为究竟创建哪个类的对象将取决于它的子类。

假设我们打算开发一个用于个人信息管理(Personal InfORMation Manager,PIM)的软件,它可以保存日常工作和生活中所需的各种信息,包括地址本、电话簿、约会提醒、日程安排等等。很显然,PIM用户界面(User Interface)的设计将是比较复杂的,因为必须为每种信息的输入、验证和修改都提供单独的界面,以便同用户进行交互。比较简单的做法是在PIM中为各种信息的处理编写相应的用户界面,但代价是将导致软件的可扩展性非常差,因为一旦今后要加入对其他信息(比如银行帐户)进行管理的功能时,就必须对PIM进行修改,添加相应的用户界面,从而最终导致PIM变得越来越复杂,结构庞大而难以维护。改进的办法是将处理各种信息的用户界面从PIM中分离出来,使PIM不再关心用户如何输入数据,如何对用户输入进行验证,以及用户如何修改信息等,所有的这些都交由一个专门的软件模块来完成,而PIM要做的只是提供一个对这些个人信息进行管理的总体框架。

在具体实现时可以设计一个通用接口Editable,并且让所有处理特定个人信息(如通信地址和电话号码)的用户界面都继承于它,而PIM则通过Editable提供的方法getEditor()获得Editor的一个实例,并利用它来对用户输入进行统一的处理。例如,当用户完成输入之后,PIM可以调用Editor中的方法getContent()来获取用户输入的数据,或者调用resetUI()来清除用户输入的数据。在采用这一体系结构之后,如果要扩展PIM的功能,只需添加与之对应的Editable和Editor就可以了,而不用对PIM本身进行修改。

现在离目标还有一步之遥,由于Editable和Editor都只是通用的接口,但PIM却需要对它们的子类进行实例化,此时自然应该想到运用工厂方法模式,为PIM定义一个EditableFactory接口来创建Editable的对象。这样一来,整个PIM的体系结构就将如图2所示。

Python中工厂方法模式有什么用

Editable接口定义了一个公共的构造性方法(builder method)getEditor(),它返回一个Editor对象,其完整的代码如清单1所示。任何一项个人信息都拥有自己独立的用户界面(Editor),负责获取数据并在需要的时候进行修改,而PIM唯一要做事情的只是通过Editable来获得Editor,并利用它来对用户输入的数据进行相应的操作。

代码清单1:editable.py  class Editable:    """ 个人信息用户界面的公共接口 """    # 获得个人信息编辑界面    def getEditor(self):  pass

Editor接口给出了处理所有个人信息的公共接口,其完整的代码如清单2所示。PIM通过调用getUI()方法能够获得与用户进行交互的UI组件,根据当前正在处理的个人信息的不同,这些组件可能简单到只是一个文本输入框,也可以复杂到是一个包含了多个图形控件(Widget)的对话框。利用Editor提供的getContent()、commitChanges()和resetUI()方法,PIM还可以获取、提交或者清空用户输入的个人信息。在引入Editor之后, PIM就能够从处理特定个人信息的用户界面中解脱出来,从而可以将注意力集中在如何对这些信息进行统一管理的问题上。

代码清单2:editor.py  class Editor:    """ 用户使用特定的Editor来编辑个人信息 """    # 获取代表用户界面(UI)的对象    def getUI(self):      pass        # 获取用户输入的数据    def getContent(self):      pass    # 提交用户输入的数据    def commitChanges(self):      pass          # 清空用户输入的数据    def resetUI(self):      pass

EditableAddress是Editable的一个具体实现,PIM使用它来处理个人地址信息,其完整的代码如清单3所示。

代码清单3:editableaddress.py  from editor import Editor  from editable import Editable  import Tkinter  class EditableAddress(Editable):    """ 用于处理个人地址信息的Editable """        # 构造函数    def __init__(self, master):      self.master = master      self.name = ""     self.province = ""     self.city = ""     self.street = ""     self.zipcode = ""     self.editor = AddressEditor(self)          # 获取相关联的Editor    def getEditor(self):      return self.editor          class AddressEditor(Editor, Tkinter.Frame):    """ 用于处理个人地址信息的Editor """        # 构造函数    def __init__(self, owner):      Tkinter.Frame.__init__(self, owner.master)      self.owner = owner      self.name = Tkinter.StringVar()      self.province = Tkinter.StringVar()      self.city = Tkinter.StringVar()      self.street = Tkinter.StringVar()      self.zipcode = Tkinter.StringVar()      self.createWidgets()         # 构造用户界面    def createWidgets(self):      # 姓名      nameFrame = Tkinter.Frame(self)      nameLabel = Tkinter.Label(nameFrame, text="Name:")      nameEntry = Tkinter.Entry(nameFrame, textvariable=self.name)      nameLabel.config(anchor=Tkinter.E, width=8, pady=3)      nameLabel.pack(side=Tkinter.LEFT)      nameEntry.pack(side=Tkinter.LEFT)      nameFrame.pack()            # 省份      provinceFrame = Tkinter.Frame(self)      provinceLabel = Tkinter.Label(provinceFrame, text="Province:")      provinceEntry = Tkinter.Entry(provinceFrame, textvariable=self.province)      provinceLabel.config(anchor=Tkinter.E, width=8, pady=3)      provinceLabel.pack(side=Tkinter.LEFT)      provinceEntry.pack(side=Tkinter.LEFT)      provinceFrame.pack()      # 城市      cityFrame = Tkinter.Frame(self)      cityLabel = Tkinter.Label(cityFrame, text="City:")      cityEntry = Tkinter.Entry(cityFrame, textvariable=self.city)      cityLabel.config(anchor=Tkinter.E, width=8, pady=3)      cityLabel.pack(side=Tkinter.LEFT)      cityEntry.pack(side=Tkinter.LEFT)      cityFrame.pack()            # 街道      streetFrame = Tkinter.Frame(self)      streetLabel = Tkinter.Label(streetFrame, text="Street:")      streetEntry = Tkinter.Entry(streetFrame, textvariable=self.street)      streetLabel.config(anchor=Tkinter.E, width=8, pady=3)      streetLabel.pack(side=Tkinter.LEFT)      streetEntry.pack(side=Tkinter.LEFT)      streetFrame.pack()            # 邮编      zipcodeFrame = Tkinter.Frame(self)      zipcodeLabel = Tkinter.Label(zipcodeFrame, text="ZIP Code:")      zipcodeEntry = Tkinter.Entry(zipcodeFrame, textvariable=self.zipcode)      zipcodeLabel.config(anchor=Tkinter.E, width=8, pady=3)      zipcodeLabel.pack(side=Tkinter.LEFT)      zipcodeEntry.pack(side=Tkinter.LEFT)      zipcodeFrame.pack()          # 重载Editor中的方法,获取代表用户界面(UI)的对象    def getUI(self):      return self        # 重载Editor中的方法,获取用户输入的数据    def getContent(self):      content  = "    Name: " + self.name.get() + "\n"      content += "Province: " + self.province.get() + "\n"       content += "    City: " + self.city.get() + "\n"       content += "  Street: " + self.street.get() + "\n"       content += "ZIP Code: " + self.zipcode.get()      return content        # 重载Editor中的方法,提交用户输入的数据    def commitChanges(self):      selfself.owner.name = self.name.get()      selfself.owner.province = self.province.get()      selfself.owner.city = self.city.get()      selfself.owner.street = self.street.get()      selfself.owner.zipcode = self.zipcode.get()    # 重载Editor中的方法,清空用户输入的数据    def resetUI(self):      self.name.set("")      self.province.set("")      self.city.set("")      self.street.set("")      self.zipcode.set("")

EditablePhone是Editable的另一个具体实现,PIM使用它来处理个人电话号码,其完整的代码如清单4所示。

代码清单4:editablephone.py  from editor import Editor  from editable import Editable  import Tkinter  class EditablePhone(Editable):    """ 用于处理个人电话号码的Editable """        # 构造函数    def __init__(self, master):      self.master =master      self.areaCode = "";      self.phoneNumber = ""     self.editor = PhoneEditor(self)          # 获取相关联的Editor    def getEditor(self):      return self.editor      class PhoneEditor(Editor, Tkinter.Frame):    """ 用于处理个人电话号码的Editor """        # 构造函数    def __init__(self, owner):      self.owner = owner      Tkinter.Frame.__init__(self, self.owner.master)      self.areaCode = Tkinter.StringVar()      self.phoneNumber = Tkinter.StringVar()      # 构造用户界面      codeLabel = Tkinter.Label(self, text="Area Code:")      codeEntry = Tkinter.Entry(self, textvariable=self.areaCode)      codeLabel.config(anchor=Tkinter.E, width=12, pady=3)      codeLabel.grid(row=0, column=0)      codeEntry.grid(row=0, column=1)            numberLabel = Tkinter.Label(self, text="Phone Number:")      numberEntry = Tkinter.Entry(self, textvariable=self.phoneNumber)      numberLabel.config(anchor=Tkinter.E, width=12, pady=3)      numberLabel.grid(row=1, column=0)      numberEntry.grid(row=1, column=1)          # 重载Editor中的方法,获取代表用户界面(UI)的对象    def getUI(self):      return self        # 重载Editor中的方法,获取用户输入的数据    def getContent(self):      content  = "   Area Code: " + self.areaCode.get() + "\n"      content += "Phone Number: " + self.phoneNumber.get() + "\n"       return content       # 重载Editor中的方法,提交用户输入的数据    def commitChanges(self):      selfself.owner.areaCode = self.areaCode.get()      selfself.owner.phoneNumber = self.phoneNumber.get()          # 重载Editor中的方法,清空用户输入的数据    def resetUI(self):      self.areaCode.set("")      self.phoneNumber.set("")

EditableFactory接口是在PIM中应用工厂方法模式的核心,其完整的代码如清单5所示。与简单工厂模式中负责创建所有对象的"超级类"不同,EditableFactory只定义了如何实例化Editable的工厂方法createEditable(),并不掌握它们的生杀大权,真正负责完成创建工作的是EditableFactory的子类。

代码清单5:editablefactory.py  class EditableFactory:    """ 用于创建Editable的工厂类 """        #  实例化Editable对象    def createEditable(self, master):      pass

EditableAddressFactory是EditableFactory的一个具体实现,PIM使用它来实例化EditableAddress对象,其完整的代码如清单6所示。

代码清单6:editableaddressfactory.py  from editablefactory import EditableFactory  from editableaddress import EditableAddress  class EditableAddressFactory(EditableFactory):    """ 用于创建EditableAddress的工厂类 """        # 重载EditableFactory中的方法,实例化EditableAddress对象    def createEditable(self, master):      address = EditableAddress(master)      return address

EditablePhoneFactory是EditableFactory的另一个具体实现,PIM使用它来实例化EditablePhone对象,其完整的代码如清单7所示。

代码清单7:editablephonefactory.py  from editablefactory import EditableFactory  from editablephone import EditablePhone  class EditablePhoneFactory(EditableFactory):    """ 用于创建EditablePhone的工厂类 """        # 重载EditableFactory中的方法,实例化EditablePhone对象    def createEditable(self, master):      phone = EditablePhone(master)      return phone

所有这些辅助类都定义好之后,接下去就可以编写PIM类了,它提供了一个对各种个人信息进行统一管理的框架,其完整的代码如清单8所示。

代码清单8:pim.py  from editablephone import EditablePhone  from editableaddressfactory import EditableAddressFactory  from editablephonefactory import EditablePhoneFactory  import Tkinter  class PIM:    """ 个人信息管理 """        # 构造函数    def __init__(self):      mainFrame = Tkinter.Frame()          mainFrame.master.title("PIM")      # 命令按钮      addressButton = Tkinter.Button(mainFrame, width=10, text="Address")      phoneButton = Tkinter.Button(mainFrame, width=10, text="Phone")      commitButton = Tkinter.Button(mainFrame, width=10, text="Commit")          resetButton = Tkinter.Button(mainFrame, width=10, text="Reset")              addressButton.config(command=self.addressClicked)      phoneButton.config(command=self.phoneClicked)          commitButton.config(command=self.commitClicked)              resetButton.config(command=self.resetClicked)              addressButton.grid(row=0, column=1, padx=10, pady=5, stick=Tkinter.E)      phoneButton.grid(row=1, column=1, padx=10, pady=5, stick=Tkinter.E)      commitButton.grid(row=2, column=1, padx=10, pady=5, stick=Tkinter.E)      resetButton.grid(row=3, column=1, padx=10, pady=5, stick=Tkinter.E)         # 用来容纳各类Editor的容器      self.editorFrame = Tkinter.Frame(mainFrame)      self.editorFrame.grid(row=0, column=0, rowspan=4)      self.editorFrame.grid_configure(stick=Tkinter.N, pady=15)      self.editor = Tkinter.Frame(self.editorFrame)      self.editor.grid()         # 个人信息显示区域      self.content = Tkinter.StringVar()      self.contentLabel = Tkinter.Label(mainFrame, width=50, height=5)      self.contentLabel.configure(textvariable=self.content)      self.contentLabel.configure(anchor=Tkinter.W, font="Arial 10 italic bold")      self.contentLabel.configure(relief=Tkinter.RIDGE, pady=5, padx=10)      self.contentLabel.grid(row=4, column=0, columnspan=2)            mainFrame.pack()      mainFrame.mainloop()          # Address按钮的回调函数    def addressClicked(self):      address = EditableAddressFactory().createEditable(self.editorFrame)      self.editor.grid_remove()      self.editor = address.getEditor()      self.editor.getUI().grid()    # Phone按钮的回调函数    def phoneClicked(self):      phone = EditablePhoneFactory().createEditable(self.editorFrame)      self.editor.grid_remove()      self.editor = phone.getEditor()      self.editor.getUI().grid()          # Commit按钮的回调函数    def commitClicked(self):      content = self.editor.getContent()      self.content.set(content)        # Reset按钮的回调函数    def resetClicked(self):      self.editor.resetUI()        # 主函数  if (__name__ == "__main__"):    app = PIM()

图3是PIM在运行时的界面效果。

Python中工厂方法模式有什么用

三、一般结构

工厂方法模式是简单工厂模式的进一步抽象和推广,它不仅保持了简单工厂模式能够向客户隐藏类的实例化过程这一优点,而且还通过多态性克服了工厂类过于复杂且不易于扩展的缺点。在工厂方法模式中,处于核心地位的工厂类不再负责所有产品的创建,而是将具体的创建工作交由子类去完成。工厂方法模式中的核心工厂类经过功能抽象之后,成为了一个抽象的工厂角色,仅负责给出具体工厂子类必须实现的接口,而不涉及哪种产品类应当被实例化这一细节。工厂方法模式的一般性结构如图4所示,图中为了简化只给出了一个产品类和一个工厂类,但在实际系统中通常需要设计多个产品类和多个工厂类。

Python中工厂方法模式有什么用

工厂方法模式的实质是将对象的创建延迟到其子类实现,即由子类根据当前情况动态决定应该实例化哪一个产品类。从上图可以看出,工厂方法模式涉及到抽象工厂角色、具体工厂角色、抽象产品角色和具体产品角色四个参与者。

◆抽象工厂(Creator)角色:是工厂方法模式的核心,它负责定义创建抽象产品对象的工厂方法。抽象工厂不能被外界直接调用,但任何在模式中用于创建产品对象的工厂类都必须实现由它所定义的工厂方法。

具体工厂(Concrete Creator)角色:是工厂方法模式的对外接口,它负责实现创建具体产品对象的内部逻辑。具体工厂与应用密切相关,可以被外界直接调用,创建所需要的产品。

抽象产品(Product)角色:是工厂方法模式所创建的所有对象的父类,它负责描述所有具体产品共有的公共接口。

具体产品(Concrete Product)角色:是工厂方法模式的创建目标,所有创建的对象都是充当这一角色的某个具体类的实例。

抽象工厂角色负责声明工厂方法(factory method),用来"生产"抽象产品,以下是抽象工厂的示例性Python代码:

代码清单9:creator.py  class Creator:    """ 抽象工厂角色 """        # 创建抽象产品的工厂方法    def factoryMethod(self):      pass

具体工厂角色负责创建一个具体产品的实例,并将其返回给调用者。具体工厂是与具体产品相关的,实现时一般常用的做法是为每个具体产品定义一个具体工厂。以下是具体工厂的示例性Python代码:

代码清单10:concretecreator.py  class ConcreteCreator(Creator):    """ 具体工厂角色 """        # 创建具体产品的工厂方法    def factoryMethod(self):      product =  ConcreteProduct()      return product

抽象产品角色的主要目的是为所有的具体产品提供一个共同的接口,通常只需给出相应的声明就可以了,而不用给出具体的实现。以下是抽象产品类的示例性Python代码:

代码清单11:product.py  class Product:    """ 抽象产品角色 """        # 所有产品类的公共接口    def interface(self):      pass

具体产品角色充当最终的创建目标,一般来讲它是抽象产品类的子类,实现了抽象产品类中定义的所有工厂方法,实际应用时通常会具有比较复杂的业务逻辑。以下是具体产品类的示例性Python代码:

代码清单12:concreteproduct.py  class ConcreteProduct(Product):    """ 具体产品角色 """        # 公共接口的实现    def interface(self):      print "Concrete Product Method"


在应用工厂方法模式时,通常还需要再引入一个客户端角色,由它负责创建具体的工厂对象,然后再调用工厂对象中的工厂方法来创建相应的产品对象。以下是客户端的示例性Python代码:

代码清单13:client.py  class Client:    """ 客户端角色 """        def run(self):      creator = ConcreteCreator()      product = creator.factoryMethod()      product.interface()  # 主函数  if (__name__ == "__main__"):    client = Client()    client.run()


在这个简单的示意性实现里,充当具体产品和具体工厂角色的类都只有一个,但在真正的实际应用中,通常遇到的都是同时会有多个具体产品类的情况,此时相应地需要提供多个具体工厂类,每个具体工厂都负责生产对应的具体产品。

工厂方法模式的活动序列如图5所示,客户端Client首先创建ConcreteCreator对象,然后调用ConcreteCreator对象的工厂方法factoryMethod(),由它负责"生产"出所需要的ConcreteProduct对象。

Python中工厂方法模式有什么用

四、实际运用

使用工厂方法模式可以在不修改具体工厂角色的情况下引入新的产品,这一点无疑使得工厂方法模式具有比简单工厂模式更好的可扩展性。在开发实际的软件系统时,通常是先设计产品角色,然后才开始设计工厂角色,而复杂的需求导致将在抽象产品和具体产品之间形成非常庞大的树状结构,如图6所示。

Python中工厂方法模式有什么用

在上面的产品等级结构中,出现了多于一个的抽象产品类,以及多于两个的类层次,这是在构造真实系统中经常遇到的情况。在为这一软件体系结构应用工厂方法模式时,通常的做法是按照产品的等级结构再设计一个相同的工厂等级结构,如图7所示。

Python中工厂方法模式有什么用

定义工厂角色的目的是为了创建相应的产品角色,因此整个系统的架构将如图8所示。这一结构常常被称为平行的类层次(parallel class hierarchies),它使得一个类能够将它的一些职责委托给另一个独立的类,而工厂方法则是联系两者之间的纽带。工厂方法模式并没有限制产品等级的层数,虽然前面给出的一般性结构中只有两个层次(抽象产品层和具体产品层),但在实际运用时却往往需要更加复杂的产品层次。

Python中工厂方法模式有什么用

在工厂方法模式的一般性结构中,每当具体工厂类中的工厂方法被请求时,都会调用具体产品类的构造函数来创建一个新的产品实例,然后再将这个实例提供给客户端。但在实际软件系统中应用工厂方法模式时,工厂方法所做的事情可能更加复杂,其中最常见到的一种情况是循环使用产品对象。所采用的策略是将工厂对象创建的所有产品对象登记到一个对象池(object pool)中,这样每当客户请求工厂方法创建相应的产品对象时,可以先从对象池中查询符合条件的产品对象,如果对象池中恰巧有这样的对象,那就直接将这个产品对象返回给客户端;如果对象池中没有这样的对象,那就创建一个新的满足要求的产品对象,将其登记到对象池中,然后再返回给客户端。

工厂方法模式依赖于工厂角色和产品角色的多态性,但在实际运用时这个模式可能出现退化,其表现就是多态性的丧失。在工厂方法模式中,所有的具体工厂对象应该共享一个抽象的超类,或者换句话说,应当有多个具体工厂类作为一个抽象工厂类的子类存在于工厂等级结构中,但如果工厂等级结构中只有一个具体工厂类的话,那么抽象工厂角色可以省略。当抽象工厂角色被省略时,工厂方法模式就发生了退化,这一退化表现为工厂角色多态性的丧失,退化后的模式仍然可以发挥部分工厂方法模式的作用,通常被称为退化的工厂方法模式。退化的工厂方法模式在很大程度上与简单工厂模式相似,如图9所示,实际运用时可以考虑用简单工厂模式进行替代。

Python中工厂方法模式有什么用

在工厂方法模式中,从工厂方法返回的应当是抽象产品类型,而不是具体产品类型,因为只有这样才能保证产品角色的多态性。也就是说,调用工厂方法的客户端可以针对抽象产品类进行编程,而不必依赖于具体产品类。在实际运用时有可能会出现一种很特殊的情况,那就是工厂方法只需要返回一个具体产品类,此时工厂方法模式的功能同样会发生退化,但这一退化将表现为产品角色多态性的丧失,如图10所示。严格说来,当工厂方法模式出现这一退化时,就不能再称为工厂方法模式了,因为客户端从工厂方法的静态类型就可以判断出将要得到的是什么类型的对象,而这一点恰好违背了工厂方法模式的初衷。

Python中工厂方法模式有什么用

五、优势和不足

在工厂方法模式中,工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节。工厂方法模式的核心是一个抽象工厂类,各种具体工厂类通过从抽象工厂类中将工厂方法继承下来,使得客户可以只关心抽象产品和抽象工厂,完全不用理会返回的是哪一种具体产品,也不用关心它是如何被具体工厂创建的。

基于工厂角色和产品角色的多态性设计是工厂方法模式的关键,它使得工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,显然是因为所有的具体工厂类都具有同一抽象父类。

使用工厂方法模式的另一个优点是在系统中加入新产品时,不需要对抽象工厂和抽象产品提供的接口进行修改,而只要添加一个具体工厂和具体产品就可以了,没有必要修改客户端,也没有必须修改其他的具体工厂和具体产品,系统的可扩展性非常好。优秀的面向对象设计鼓励使用封装(Encapsulation)和委托(Delegation)来构造软件系统,而工厂方法模式则是使用了封装和委托的典型例子,其中封装是通过抽象工厂来体现的,而委托则是通过抽象工厂将创建对象的责任完全交给具体工厂来体现的。

使用工厂方法模式的缺点是在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,当两者都比较简单时,系统的额外开销相对较大。

以上是“Python中工厂方法模式有什么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网Python频道!

--结束END--

本文标题: Python中工厂方法模式有什么用

本文链接: https://lsjlt.com/news/289529.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python中工厂方法模式有什么用
    这篇文章主要为大家展示了“Python中工厂方法模式有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Python中工厂方法模式有什么用”这篇文章吧。工厂方法(Factory Method)...
    99+
    2023-06-17
  • php设计模式中工厂模式有什么用
    这篇文章将为大家详细讲解有关php设计模式中工厂模式有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。使用工厂模式的目的或目标?工厂模式的最大优点在于创建对象上面,就...
    99+
    2024-04-02
  • JavaScript抽象工厂及工厂方法模式是什么
    这篇文章主要介绍“JavaScript抽象工厂及工厂方法模式是什么”,在日常操作中,相信很多人在JavaScript抽象工厂及工厂方法模式是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,...
    99+
    2024-04-02
  • Java工厂模式之简单工厂,工厂方法,抽象工厂模式详解
    目录1、简单工厂模式1.定义2.代码案例3.适用场景4.优缺点2、工厂方法模式1.定义2.代码案例3.适用场景4.优缺点3、抽象工厂模式1.定义2.代码案例3.适用场景4.优缺点4、...
    99+
    2024-04-02
  • java中抽象工厂模式与工厂方法模式的区别
    一、简单工厂模式特点:它是一个具体的类,非接口 抽象类。有一个重要的create()方法,利用if或者 switch创建产品并返回。create()方法通常是静态的,所以也称之为静态工厂。缺点:扩展性差(我想增加一种面条,除了新增一个面条产...
    99+
    2015-05-09
    java入门 java 抽象工厂模式 工厂方法模式 区别
  • 工厂方法模式介绍
    韩敬海 设计模式(Java版) (一)定义 定义一个创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。 工厂方法涉及的角色有: 1 .抽象工厂角色:工厂方法模式的核心,与应用系统无关,任何创建对象的工厂类必...
    99+
    2023-08-30
    工厂方法模式
  • Java简单工厂,工厂方法,抽象工厂模式怎么实现
    这篇文章主要讲解了“Java简单工厂,工厂方法,抽象工厂模式怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java简单工厂,工厂方法,抽象工厂模式怎么实现”吧!1、简单工厂模式1.定...
    99+
    2023-06-29
  • php工厂方法模式的好处是什么
    本文操作环境:Windows10系统、PHP7.1版、Dell G3电脑。php工厂方法模式的好处是什么此模式中,通过定义一个抽象的核心工厂类,并定义创建产品对象的接口,创建具体产品实例的工作延迟到其工厂子类去完成。这样做的好处是核心类只关...
    99+
    2014-07-20
    php
  • python工厂方法模式原理与实现
    目录一、简介二、工厂方法模式的主要角色三、简单工厂模式四、工厂模式五、抽象工厂模式总结一、简介 工厂模式是属于创建型模式,它提供了一种创建对象的最佳方式。 在工厂模式中,我们在创建对...
    99+
    2024-04-02
  • java中的工厂模式是什么
    本篇内容介绍了“java中的工厂模式是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!目录前言试例 创建饮料接口(或者抽象类) 具体饮料类...
    99+
    2023-06-20
  • C#实现工厂方法模式
    场景:简单工厂时候,我设计了一个场景,有三种剑去打怪,这时候,需求变化了,我三种剑变成了,匕首、剑以及木棒,想要用工厂方法来实现,怎么弄? 1.上文讲过简单工厂模式,它的最大优点在于...
    99+
    2024-04-02
  • java什么是工厂模式
    工厂方法模式(Factory Method)工厂方法模式分为三种:普通工厂模式,就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。首先看下关系图:举例如下:(我们举一个发送邮件和短信的例子)首先,创建二者的共同接口:public ...
    99+
    2017-11-03
    java入门 java 工厂模式
  • 什么是Javascript工厂模式
    这篇文章主要介绍“什么是Javascript工厂模式”,在日常操作中,相信很多人在什么是Javascript工厂模式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”什么是Jav...
    99+
    2024-04-02
  • 什么是php工厂模式
    PHP工厂模式是一种创建对象的设计模式,它通过一个工厂类来创建其他类的对象,而不是直接在代码中使用new关键字实例化对象。工厂模式可...
    99+
    2023-08-24
    PHP
  • Springboot中实现策略模式+工厂模式的方法
      策略模式和工厂模式相信大家都比较熟悉,但是大家有没有在springboot中实现策略和工厂模式   具体策略模式和工厂模式的UML我就不给出来了,使用这个这两个模式主要是防止程序...
    99+
    2024-04-02
  • java中有哪些工厂模式
    今天就跟大家聊聊有关java中有哪些工厂模式,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。简单工厂简单工厂模式是属于创建型模式,是工厂模式的一种。简单工厂模式是由一个工厂对象决定创建...
    99+
    2023-06-20
  • Java工厂方法模式怎么实现
    这篇文章主要讲解了“Java工厂方法模式怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java工厂方法模式怎么实现”吧!一、什么是工厂方法模式?工厂方法模式:也叫虚拟构造器模式或者多...
    99+
    2023-06-29
  • Java设计模式之工厂方法和抽象工厂
    全网最详细的工厂设计模式,本文主要是创建型设计模式中的工厂方法和抽象工厂,先由传统实现方式引出问题,接着对代码改进到简单工厂,后扩展到工厂方法,最后是抽象工厂模式,文中包括概念理解和...
    99+
    2024-04-02
  • 详解设计模式中的工厂方法模式在Python程序中的运用
    工厂方法(Factory Method)模式又称为虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,属于类的创建型模式。在工厂方法模式中,父...
    99+
    2022-06-04
    模式 详解 工厂
  • 设计模式之什么是工厂模式
    本篇内容主要讲解“设计模式之什么是工厂模式”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“设计模式之什么是工厂模式”吧! 01 简单工厂方法简单工厂方法...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作