Skip to content

工厂模式

概念

  • 属于创建型模式,又叫静态工厂方法(Static Factory Method)模式,但不属于23中GOF设计模式之一。
  • 特点是可以根据参数的不同返回不同的实例。
  • 工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

结构

Image title

工厂模式结构图

代码示例

  • product.go

    package factory
    
    // 实现一个抽象的产品
    type Product interface {
        SetName(name string)
        GetName() string
    }
    
    // 实现一个具体的产品:产品1
    type Product1 struct {
        name string
    }
    
    func (p1 *Product1) SetName(name string) {
        p1.name = name
    }
    
    func (p1 *Product1) GetName() string {
        return "产品1的name为" + p1.name
    }
    
    // 实现一个具体的产品:产品2
    type Product2 struct {
        name string
    }
    
    func (p2 *Product2) SetName(name string) {
        p2.name = name
    }
    
    func (p2 *Product2) GetName() string {
        return "产品2的name为" + p2.name
    }
    
    type productType int
    
    const (
        p1 productType = iota
        p2
    )
    
    // 实现简单工厂类
    type productFactory struct {
    }
    
    func (pf productFactory) Create(productType productType) Product {
        if productType == p1 {
            return &Product1{}
        }
        if productType == p2 {
            return &Product2{}
        }
        return nil
    }
    

  • product_demo.go

    package factory
    
    import (
        "fmt"
        "testing"
    )
    
    func TestProduct_Create(t testing.T) {
        product1 := &Product1{}
        product1.SetName("p1")
        fmt.Println(product1.GetName())
        /*
            === RUN TestProduct_Create
            产品1的name为:p1
            --- PASS: TestProduct_Create
            PASS
        */
    }
    
    func TestProductFactory_Create(t testing.T) {
        // 直接实例化工厂类
        productFactory := productFactory{}
        product1 := productFactory.Create(p1)
        product1.SetName("p1")
        fmt.Println(product1.GetName())
    
        product2 := productFactory.Create(p2)
        product2.SetName("p2")
        fmt.Println(product2.GetName())
    
        /*
            === RUN TestProductFactory_Create
            产品1的name为:p1
            产品2的name为:p2
            --- PASS: TestProductFactory_Create
            PASS
        */
    }
    

实战模拟

  • 工厂模式实现一个缓存库,支持set、get方法,同时模拟支持Redis和Memcache
  • cache.go
    package factory_cache
    
    import "errors"
    
    type Cache interface { // 定义一个Cache,作为父类
        Set(key, value string)
        Get(key string) string
    }
    
    type RedisCache struct { // 实现具体的Cache:RedisCache
        data map[string]string
    }
    
    func (redis *RedisCache) Set(key, value string) {
        redis.data[key] = value
    }
    
    func (redis *RedisCache) Get(key string) string {
        return "redis: " + redis.data[key]
    }
    
    type MemCache struct { // 实现具体的Cache:Memcache
        data map[string]string
    }
    
    func (mem *MemCache) Set(key, value string) {
        mem.data[key] = value
    }
    
    func (mem *MemCache) Get(key string) string {
        return "mem: " + mem.data[key]
    }
    
    type cacheType int
    
    const (
        redis cacheType = iota
        mem
    )
    
    type CacheFactory struct { // 实现Cache的工厂
    }
    
    func (factory *CacheFactory) Create(cacheType cacheType) (Cache, error) {
        if cacheType == redis {
            return &RedisCache{
                data: map[string]string{},
            }, nil
        }
    
        if cacheType == mem {
            return &MemCache{
                data: map[string]string{},
            }, nil
        }
    
        return nil, errors.New("error cache type")
    }
    
  • cache_test.go
    package factory_cache
    
    import (
        "fmt"
        "testing"
    )
    
    func TestCacheFactory_Create(t *testing.T) {
        cacheFactory := &CacheFactory{}
        redis, error := cacheFactory.Create(redis)
        if error != nil {
            t.Error(error)
        }
    
        redis.Set("k1", "v1")
    
        fmt.Println(redis.Get("k1"))
    
        mem, error := cacheFactory.Create(mem)
        if error != nil {
            t.Error(error)
        }
    
        mem.Set("k2", "k2")
    
        fmt.Println(mem.Get("k2"))
    }
    
    
    
    // 输出
    /usr/local/go/bin/go tool test2json -t /private/var/folders/7w/0j7vff4j1kz5_g43cf_vqlg00000gp/T/GoLand/___TestCacheFactory_Create_in_designpattern_factory_cache.test -test.v -test.paniconexit0 -test.run ^\QTestCacheFactory_Create\E$
    === RUN   TestCacheFactory_Create
    redis: v1
    mem: k2
    --- PASS: TestCacheFactory_Create (0.00s)
    PASS
    
    Process finished with the exit code 0
    

工厂模式总结

  • 优点:实现了解耦
  • 缺点:违背了“开闭原则”
  • 适合:创建的对象比较少