微信登录

面向对象设计模式 - 工厂模式 - 创建对象的模式

Lua 面向对象设计模式 - 工厂模式 - 创建对象的模式

一、引言

在软件开发中,对象的创建是一个常见且基础的操作。然而,直接在代码中硬编码对象的创建过程会导致代码的耦合度增加,可维护性和可扩展性变差。工厂模式作为一种创建型设计模式,能够很好地解决这些问题。它将对象的创建和使用分离,使得代码更加灵活、易于维护。本文将详细介绍 Lua 中工厂模式的概念、实现方式以及应用场景,并给出相应的演示代码。

二、工厂模式概述

工厂模式是一种创建对象的设计模式,它提供了一种创建对象的方式,将对象的创建逻辑封装在一个工厂类(或函数)中,而不是在使用对象的地方直接创建。这样做的好处是:

  • 解耦:将对象的创建和使用分离,降低代码的耦合度。
  • 可维护性:当对象的创建逻辑发生变化时,只需要修改工厂类(或函数),而不需要修改使用对象的代码。
  • 可扩展性:可以方便地添加新的对象类型,只需要在工厂类(或函数)中添加相应的创建逻辑。

工厂模式主要分为三种类型:简单工厂模式、工厂方法模式和抽象工厂模式。下面我们将分别介绍这三种模式在 Lua 中的实现。

三、简单工厂模式

3.1 概念

简单工厂模式是工厂模式的最简单形式,它定义了一个工厂函数,根据传入的参数来创建不同类型的对象。

3.2 演示代码

  1. -- 定义不同类型的对象类
  2. local Circle = {}
  3. function Circle:new()
  4. local obj = {}
  5. setmetatable(obj, self)
  6. self.__index = self
  7. return obj
  8. end
  9. function Circle:draw()
  10. print("Drawing a circle.")
  11. end
  12. local Rectangle = {}
  13. function Rectangle:new()
  14. local obj = {}
  15. setmetatable(obj, self)
  16. self.__index = self
  17. return obj
  18. end
  19. function Rectangle:draw()
  20. print("Drawing a rectangle.")
  21. end
  22. -- 简单工厂函数
  23. local ShapeFactory = {}
  24. function ShapeFactory.createShape(shapeType)
  25. if shapeType == "circle" then
  26. return Circle:new()
  27. elseif shapeType == "rectangle" then
  28. return Rectangle:new()
  29. else
  30. return nil
  31. end
  32. end
  33. -- 使用简单工厂创建对象
  34. local circle = ShapeFactory.createShape("circle")
  35. circle:draw()
  36. local rectangle = ShapeFactory.createShape("rectangle")
  37. rectangle:draw()

3.3 代码解释

  • 首先,我们定义了两个对象类 CircleRectangle,它们都有一个 draw 方法用于绘制图形。
  • 然后,我们创建了一个简单工厂函数 ShapeFactory.createShape,根据传入的 shapeType 参数来创建不同类型的对象。
  • 最后,我们使用工厂函数创建了一个圆形和一个矩形对象,并调用它们的 draw 方法。

3.4 优缺点

  • 优点:实现简单,将对象的创建逻辑封装在一个函数中,降低了代码的耦合度。
  • 缺点:工厂函数的职责过重,当需要添加新的对象类型时,需要修改工厂函数的代码,不符合开闭原则。

四、工厂方法模式

4.1 概念

工厂方法模式将对象的创建延迟到子类中进行,每个具体的子类负责创建特定类型的对象。这样,当需要添加新的对象类型时,只需要创建一个新的子类即可,不需要修改原有的工厂类。

4.2 演示代码

  1. -- 定义抽象工厂类
  2. local ShapeFactory = {}
  3. function ShapeFactory:new()
  4. local obj = {}
  5. setmetatable(obj, self)
  6. self.__index = self
  7. return obj
  8. end
  9. function ShapeFactory:createShape()
  10. error("This method must be overridden!")
  11. end
  12. -- 定义具体的工厂子类
  13. local CircleFactory = ShapeFactory:new()
  14. function CircleFactory:createShape()
  15. local Circle = {}
  16. function Circle:new()
  17. local obj = {}
  18. setmetatable(obj, self)
  19. self.__index = self
  20. return obj
  21. end
  22. function Circle:draw()
  23. print("Drawing a circle.")
  24. end
  25. return Circle:new()
  26. end
  27. local RectangleFactory = ShapeFactory:new()
  28. function RectangleFactory:createShape()
  29. local Rectangle = {}
  30. function Rectangle:new()
  31. local obj = {}
  32. setmetatable(obj, self)
  33. self.__index = self
  34. return obj
  35. end
  36. function Rectangle:draw()
  37. print("Drawing a rectangle.")
  38. end
  39. return Rectangle:new()
  40. end
  41. -- 使用工厂方法创建对象
  42. local circleFactory = CircleFactory:new()
  43. local circle = circleFactory:createShape()
  44. circle:draw()
  45. local rectangleFactory = RectangleFactory:new()
  46. local rectangle = rectangleFactory:createShape()
  47. rectangle:draw()

3.3 代码解释

  • 首先,我们定义了一个抽象工厂类 ShapeFactory,其中的 createShape 方法是一个抽象方法,需要在子类中实现。
  • 然后,我们创建了两个具体的工厂子类 CircleFactoryRectangleFactory,分别负责创建圆形和矩形对象。
  • 最后,我们使用具体的工厂子类创建对象,并调用它们的 draw 方法。

3.4 优缺点

  • 优点:符合开闭原则,当需要添加新的对象类型时,只需要创建一个新的工厂子类,不需要修改原有的代码。
  • 缺点:类的数量会增加,代码复杂度会有所提高。

五、抽象工厂模式

5.1 概念

抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。它可以创建多个不同类型的对象,这些对象通常属于同一个产品族。

5.2 演示代码

  1. -- 定义抽象产品类
  2. local Shape = {}
  3. function Shape:new()
  4. local obj = {}
  5. setmetatable(obj, self)
  6. self.__index = self
  7. return obj
  8. end
  9. function Shape:draw()
  10. error("This method must be overridden!")
  11. end
  12. local Color = {}
  13. function Color:new()
  14. local obj = {}
  15. setmetatable(obj, self)
  16. self.__index = self
  17. return obj
  18. end
  19. function Color:fill()
  20. error("This method must be overridden!")
  21. end
  22. -- 定义具体产品类
  23. local Red = Color:new()
  24. function Red:fill()
  25. print("Filling with red color.")
  26. end
  27. local Blue = Color:new()
  28. function Blue:fill()
  29. print("Filling with blue color.")
  30. end
  31. local Circle = Shape:new()
  32. function Circle:draw()
  33. print("Drawing a circle.")
  34. end
  35. local Rectangle = Shape:new()
  36. function Rectangle:draw()
  37. print("Drawing a rectangle.")
  38. end
  39. -- 定义抽象工厂类
  40. local AbstractFactory = {}
  41. function AbstractFactory:new()
  42. local obj = {}
  43. setmetatable(obj, self)
  44. self.__index = self
  45. return obj
  46. end
  47. function AbstractFactory:createShape()
  48. error("This method must be overridden!")
  49. end
  50. function AbstractFactory:createColor()
  51. error("This method must be overridden!")
  52. end
  53. -- 定义具体工厂类
  54. local RedCircleFactory = AbstractFactory:new()
  55. function RedCircleFactory:createShape()
  56. return Circle:new()
  57. end
  58. function RedCircleFactory:createColor()
  59. return Red:new()
  60. end
  61. local BlueRectangleFactory = AbstractFactory:new()
  62. function BlueRectangleFactory:createShape()
  63. return Rectangle:new()
  64. end
  65. function BlueRectangleFactory:createColor()
  66. return Blue:new()
  67. end
  68. -- 使用抽象工厂创建对象
  69. local redCircleFactory = RedCircleFactory:new()
  70. local redCircle = redCircleFactory:createShape()
  71. local red = redCircleFactory:createColor()
  72. redCircle:draw()
  73. red:fill()
  74. local blueRectangleFactory = BlueRectangleFactory:new()
  75. local blueRectangle = blueRectangleFactory:createShape()
  76. local blue = blueRectangleFactory:createColor()
  77. blueRectangle:draw()
  78. blue:fill()

3.3 代码解释

  • 首先,我们定义了两个抽象产品类 ShapeColor,以及它们的具体产品类 CircleRectangleRedBlue
  • 然后,我们定义了一个抽象工厂类 AbstractFactory,其中包含两个抽象方法 createShapecreateColor
  • 接着,我们创建了两个具体的工厂类 RedCircleFactoryBlueRectangleFactory,分别负责创建红色圆形和蓝色矩形的产品组合。
  • 最后,我们使用具体的工厂类创建对象,并调用它们的方法。

3.4 优缺点

  • 优点:可以创建一系列相关的对象,保证了这些对象之间的兼容性。符合开闭原则,当需要添加新的产品族时,只需要创建一个新的具体工厂类。
  • 缺点:类的数量会大幅增加,代码复杂度较高。

六、总结

模式名称 特点 优点 缺点 适用场景
简单工厂模式 一个工厂函数根据参数创建不同类型的对象 实现简单,降低耦合度 工厂函数职责过重,不符合开闭原则 对象类型较少,创建逻辑简单的场景
工厂方法模式 将对象的创建延迟到子类中进行 符合开闭原则,易于扩展 类的数量增加,代码复杂度提高 需要频繁添加新对象类型的场景
抽象工厂模式 提供创建一系列相关对象的接口 可以创建一系列相关对象,保证兼容性,符合开闭原则 类的数量大幅增加,代码复杂度高 需要创建多个相关对象,且这些对象属于同一个产品族的场景

通过本文的介绍,我们了解了 Lua 中工厂模式的三种类型:简单工厂模式、工厂方法模式和抽象工厂模式。每种模式都有其适用的场景,我们可以根据实际需求选择合适的模式来提高代码的可维护性和可扩展性。