简单工厂模式在 CMP 虚拟机管理中应用

2024-04-30 15:05:43 浏览数 (2)

简单工厂模式不属于 GoF 23 个经典设计模式,但通常将它作为学习其它工厂模式的基础。

简单工厂模式(Simple Factory Pattern)

定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。

因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,属于类创建型模式。

简单工厂模式包含 3 个角色:

  1. Factory(工厂角色)
    1. 负责实现创建所有产品实例的内部逻辑。
    2. 提供了静态工厂方法 factoryMethod(),可以被外界直接调用,创建所需的产品对象。
  2. Product(抽象产品角色)
    1. 工厂类创建的所有对象的父类,封装了各种产品对象的公有方法。
  3. ConcreteProduct(具体产品角色)
    1. 简单工厂模式的创建目标,所有被创建的对象都充当这个角色的某个具体类的实例。
    2. 每个具体产品角色都继承了抽象产品角色,需要实现的抽象产品中声明的抽象方法。

在简单工厂模式中,客户端通过工厂类来创建一个产品类的实例,而无须直接使用 new 关键字来创建对象,它是工厂模式家族中最简单的一员。

应用案例

云管平台(CMP)中需要对多种类型的虚拟机进行管理,例如:OpenStack、VMware、Aliyun 等。

可以使用工厂模式来创建不同类型的虚拟机对象。

  • 未使用设计的代码

缺点:

  1. 有 3 种类型的虚拟机,每种类型虚拟机的 create 和 delete 方法都不同,势必导致产生大量冗长的代码。
  2. 每种类型虚拟机操作的代码自身也会持续增长,增长的逻辑中不确定是每种类型虚拟机都有的,还是只有一种类型或者几种类型有这样的业务,会导致代码编写位置的混乱。
  3. 每增加一种类型的虚拟机,就需要新增一个 if,随着纳管类型的增加,代码将会持续大幅增长。
代码语言:javascript复制
package main

import "fmt"

type VirtualMachine struct {
   name   string
   vmType string

   openstackField string
   vmwareField    string
   aliyunField    string
}

// 构造函数
func newVirtualMachine(name, vmType string) *VirtualMachine {

   if vmType == "OpenStack" {
      return &VirtualMachine{
         name:           name,
         vmType:         vmType,
         openstackField: "OpenStack Field",
      }
   } else if vmType == "VMware" {
      return &VirtualMachine{
         name:           name,
         vmType:         vmType,
         openstackField: "VMware Field",
      }
   } else if vmType == "Aliyun" {
      return &VirtualMachine{
         name:           name,
         vmType:         vmType,
         openstackField: "Aliyun Field",
      }
   }

   return nil
}

func (v VirtualMachine) create() {
   if v.vmType == "OpenStack" {
      fmt.Println("调用 OpenStack 接口 create 虚拟机 API")
      fmt.Println("... 大量业务逻辑代码 ...")
   } else if v.vmType == "VMware" {
      fmt.Println("调用 VMware 接口 create 虚拟机 API")
      fmt.Println("... 大量业务逻辑代码 ...")
   } else if v.vmType == "Aliyun" {
      fmt.Println("调用 Aliyun 接口 create 虚拟机 API")
      fmt.Println("... 大量业务逻辑代码 ...")
   }
}

func (v VirtualMachine) delete() {
   if v.vmType == "OpenStack" {
      fmt.Println("调用 OpenStack 接口 delete 虚拟机 API")
      fmt.Println("... 大量业务逻辑代码 ...")
   } else if v.vmType == "VMware" {
      fmt.Println("调用 VMware 接口 delete 虚拟机 API")
      fmt.Println("... 大量业务逻辑代码 ...")
   } else if v.vmType == "Aliyun" {
      fmt.Println("调用 Aliyun 接口 delete 虚拟机 API")
      fmt.Println("... 大量业务逻辑代码 ...")
   }
}

func main() {

   vm := newVirtualMachine("OpenStack", "OpenStack")
   vm.create()
   
}
  • 使用设计模式的代码

优点:

  1. 每种类型的虚拟机都有自己独立的属性,将这些独立属性放在各类虚拟机子类中,通用属性使用父类。
  2. 每种类型的虚拟机的操作都在各自方法中单独实现,避免耦合在一起相互影响。
代码语言:javascript复制
package main

type VirtualMachineInterface interface {
   create()
   delete()
}

type VirtualMachine struct {
   name   string
   vmType string
}
代码语言:javascript复制
package main

import "fmt"

type OpenStackVirtualMachine struct {
   VirtualMachine
   openStackField string
}

func (vm OpenStackVirtualMachine) create() {
   fmt.Println("调用 OpenStack 接口 create 虚拟机 API")
   fmt.Println("... 大量业务逻辑代码 ...")
}

func (vm OpenStackVirtualMachine) delete() {
   fmt.Println("调用 OpenStack 接口 delete 虚拟机 API")
   fmt.Println("... 大量业务逻辑代码 ...")
}
代码语言:javascript复制
package main

import "fmt"

type VMwareVirtualMachine struct {
   vm          VirtualMachine
   vmwareField string
}

func (vm VMwareVirtualMachine) create() {
   fmt.Println("调用 VMware 接口 create 虚拟机 API")
   fmt.Println("... 大量业务逻辑代码 ...")
}

func (vm VMwareVirtualMachine) delete() {
   fmt.Println("调用 VMware 接口 delete 虚拟机 API")
   fmt.Println("... 大量业务逻辑代码 ...")
}
代码语言:javascript复制
package main

import "fmt"

type AliyunVirtualMachine struct {
   vm          VirtualMachine
   aliyunField string
}

func (vm AliyunVirtualMachine) create() {
   fmt.Println("调用 Aliyun 接口 create 虚拟机 API")
   fmt.Println("... 大量业务逻辑代码 ...")
}

func (vm AliyunVirtualMachine) delete() {
   fmt.Println("调用 Aliyun 接口 delete 虚拟机 API")
   fmt.Println("... 大量业务逻辑代码 ...")
}
代码语言:javascript复制
package main

type VirtualMachineFactory struct {
   vmType string
}

func (factory VirtualMachineFactory) create() VirtualMachineInterface {

   if factory.vmType == "OpenStack" {
      return new(OpenStackVirtualMachine)
   } else if factory.vmType == "VMware" {
      return new(VMwareVirtualMachine)
   } else if factory.vmType == "Aliyun" {
      return new(AliyunVirtualMachine)
   }

   return nil

}

func main() {

   factory := new(VirtualMachineFactory)

   factory.vmType = "OpenStack"
   vm := factory.create()
   vm.create()

   factory.vmType = "VMware"
   vm = factory.create()
   vm.create()

   factory.vmType = "Aliyun"
   vm = factory.create()
   vm.create()
}

总结

有些对象属于一类产品,但是属性不同,业务也不同。这种对象可以使用工厂模式来创建。

使用工厂模式的好处是,将对象的创建逻辑从代码主流程中分拆出去,这样主流程代码可读性更高,同时也可以减少逻辑因为同类对象代码耦合在一起引起的逻辑混乱。

0 人点赞