目录

定义

提供一个创建对象实例的功能,而无需关心其具体的实现,被创建的对象类型可以是接口、抽象类、也可以是具体的类。

我们在平时使用接口的时候常常会有如下场景:

//定义一个接口
package main

import "fmt"

type IPerson interface {
	GetUserName(str string)
}

type user struct {
}

func (u *user) GetUserName(str string)  {
	fmt.Println("My Blog Name:",str)
}

func main() {
	var u user
	u.GetUserName("blog.68hub.com")
}

以上列子中,客户端不仅知道了接口,同时还知道了具体的实现类user接口的思想是封装隔离,而实现类user应该是被 接口IPerson封装并同客户端隔离开的(客户端根本就不应该知道具体的实现类是user)

用来解决上述问题的一个合理方案就是简单工厂。

虽然不能让模块外部知道模块内部的具体实现,但是模块内部是可以知道实现类的,而且创建接口是需要具体实现类的。 那么干脆在模块内部新建一个类,在这个类里面来创建接口,然后吧创建好的接口返回给客户端,这样外部应用只需要根据这个类来获取相应的接口对象,然后就可以操作接口定义的方法了。把这样的对象称为简单工厂Factory

客户端就可以通过Factory来获取需要的接口对象,然后调用接口的方法来实现需要的功能,而且客户端不需要关心具体的实现了。

示例代码

具体代码实现如下:

package main

import "fmt"

type IPerson interface {
	GetName(str string)
}

type User struct {}

func (u *User) GetName(str string)  {
	fmt.Println("Hello ",str)
}


// Golang 中没有构造方法,可以使用一个函数来实现
func NewFactory() IPerson {
  return &User{}
}

func main() {
  NewFactory().GetName()
}

虽然说简单工厂的方法大多是用来创建接口的,但是仔细分析就会发现,真正能实现功能的是具体的实现类,这些实现类是已经做好的,并不是真的要靠简单工厂来创造出来的。简单工厂的方法其实就是:实现了选择一个合适的实现类来使用

选择合适的实现类,来创建实例对象。

那么就需要选择的条件或者选择的参数,具体代码如下:

package main

import "fmt"

type IPerson interface {
  GetName(str string)
}

type User struct{}

func (u *User) GetName(str string) {
  fmt.Println("User ", str)
}

type Student struct{}

func (s *Student) GetName(str string) {
  fmt.Println("Student ", str)
}

func NewFactory(i int) IPerson {
  if i == 1 {
    return &User{}
  } else if i == 2 {
    return &Student{}
  }
  return nil
}

func main() {
  NewFactory(1).GetName("hello")
  NewFactory(2).GetName("world")
}

简单工厂优缺点:

优点

  • 帮助封装

    简单工厂虽然简单,但是非常友好地帮助我们实现了组件的封装,然后让组件外部能真正面向接口编程。

  • 解耦

    通过简单工厂,实现了客户端和具体实现类的解耦。

缺点

  • 可能增加客户端的复杂度

    如果通过客户端的参数来选择具体的实现类,那么就必须让客户端能理解各个参数所代表的具体功能和含义,这样会增加的客户端使用的难度,也暴露了内部实现,这种情况可以选用可配置的方式来实现。

  • 不方便扩展子工厂

    私有化简单工厂的构造方法,使用静态方法来创建接口,也就不能通过写简单工厂类的子类来改变创建接口的方法的行为了。

合适选用简单工厂(建议)

如果想要把创建对象的职责集中管理和控制,可以选用简单工厂,一个简单工厂可以创建很多不相关的对象,可以把对外创建对象的职责集中到一个简单工厂来,从而实现集中管理和控制。

总结

简单工厂的本质是:选择实现

其重点在选择。**实现**是已经做好了的。就算实现再简单,也要由具体的实现类来实现,而不是在简单工厂里面来实现。简单工厂的目的在于为了客户端来选择相应的实现,从而使得客户端和实现之间解耦。

实现简单工厂的难点就在于__“如何选择”__实现,可以是静态参数,可以实现成为动态的参数,比如在运行期间,由工厂方法读取某个内存的值,或者是去读取数据库中的值,然后根据这个值来选择具体的实现。

参考

研磨设计模式-简单工厂