然后编写一个单元测试来检验我们的代码:
func TestCipherFactory(t *testing.T) { var f ICipherFactory = NewAESCipherFactory() if reflect.TypeOf(f.GetCipher()) != reflect.TypeOf(&AESCipher{}) { t.Fatalf("should be AESCipher") } f = NewDESCipherFactory() if reflect.TypeOf(f.GetCipher()) != reflect.TypeOf(&DESCipher{}) { t.Fatalf("should be DESCipher") } } 小结在工厂方法模式中,定义了一个工厂接口,然后根据各个产品子类定义实现这个接口的子类工厂,通过子类工厂来返回产品实例。这样修改创建实例代码只需要修改子类工厂,新增实例时只需要新增具体工厂和具体产品,而不需要修改其它代码,符合“开闭原则”。不过,当具体产品较多的时候,系统中类的数量也会成倍的增加,一定程度上增加了系统的复杂度。而且,在实际使用场景中,可能还需要使用反射等技术,增加了代码的抽象性和理解难度。
抽象工厂下面再用加密这个例子可能不太好,不过我们假设需求都合理吧。现在需求更加细化了,分别需要 64 位 key 和 128 位 key 的 AES 加密库以及 64 位 key 和 128 位 key 的 DES 加密库。如果使用工厂方法模式,我们一共需要定义 4 个具体工厂和 4 个具体产品。
AESCipher64 AESCipher128 AESCipherFactory64 AESCipherFactory128 DESCipher64 DESCipher128 DESCipherFactory64 DESCipherFactory128这时候,我们可以把有关联性的具体产品组合成一个产品组,例如AESCipher64 和 AESCipher128,让它们通过同一个工厂 AESCipherFactory 来生产,这样就可以简化成 2 个具体工厂和 4 个具体产品
AESCipher64 AESCipher128 AESCipherFactory DESCipher64 DESCipher128 DESCipherFactory这就是抽象工厂模式。
模式结构抽象工厂共有 4 个角色:
AbstractFactory(抽象工厂):定义工厂的接口。
ConcreteFactory(具体工厂):实现抽象工厂,生产具体产品。
AbstractProduct(抽象产品):定义产品的接口。
Product(具体产品):具体的产品实例。
根据角色定义我们可以画出抽象工厂的 UML 关系图:
抽象产品和具体产品的定义与工厂方法类似:
抽象产品:
type ICipher interface { Encrypt(data, key[]byte) ([]byte, error) Decrypt(data, key[]byte) ([]byte, error) }AESCipher64:
type AESCipher64 struct { } func NewAESCipher64() *AESCipher64 { return &AESCipher64{} } func (AESCipher64) Encrypt(data, key []byte) ([]byte, error) { return nil, nil } func (AESCipher64) Decrypt(data, key []byte) ([]byte, error) { return nil, nil }AESCipher128:
type AESCipher128 struct { } func NewAESCipher128() *AESCipher128 { return &AESCipher128{} } func (AESCipher128) Encrypt(data, key []byte) ([]byte, error) { return nil, nil } func (AESCipher128) Decrypt(data, key []byte) ([]byte, error) { return nil, nil }AESCipher128:
type c struct { } func NewDESCipher64() *DESCipher64 { return &DESCipher64{} } func (DESCipher64) Encrypt(data, key []byte) ([]byte, error) { return nil, nil } func (DESCipher64) Decrypt(data, key []byte) ([]byte, error) { return nil, nil }DESCipher128:
type DESCipher128 struct { } func NewDESCipher128() *DESCipher128 { return &DESCipher128{} } func (DESCipher128) Encrypt(data, key []byte) ([]byte, error) { return nil, nil } func (DESCipher128) Decrypt(data, key []byte) ([]byte, error) { return nil, nil }抽象工厂角色和工厂方法相比需要增加 GetCipher64 和 GetCipher128 两个方法定义:
type ICipherFactory interface { GetCipher64() ICipher GetCipher128() ICipher }然后分别实现 AESCipherFactory 和 DesCipherFactory 两个具体工厂:
AESCipherFactory:
type AESCipherFactory struct { } func (AESCipherFactory) GetCipher64() ICipher { return NewAESCipher64() } func (AESCipherFactory) GetCipher128() ICipher { return NewAESCipher128() } func NewAESCipherFactory() *AESCipherFactory { return &AESCipherFactory{} }DESCipherFactory:
type DESCipherFactory struct { } func (DESCipherFactory) GetCipher64() ICipher { return NewDESCipher64() } func (DESCipherFactory) GetCipher128() ICipher { return NewDESCipher128() } func NewDESCipherFactory() *DESCipherFactory { return &DESCipherFactory{} }编写单元测试验证我们的代码:
func TestAbstractFactory(t *testing.T) { var f = NewCipherFactory("AES") if reflect.TypeOf(f.GetCipher64()) != reflect.TypeOf(&AESCipher64{}) { t.Fatalf("should be AESCipher64") } if reflect.TypeOf(f.GetCipher128()) != reflect.TypeOf(&AESCipher128{}) { t.Fatalf("should be AESCipher128") } f = NewCipherFactory("DES") if reflect.TypeOf(f.GetCipher64()) != reflect.TypeOf(&DESCipher64{}) { t.Fatalf("should be DESCipher64") } if reflect.TypeOf(f.GetCipher128()) != reflect.TypeOf(&DESCipher128{}) { t.Fatalf("should be DESCipher128") } } 小结