[Design Pattern With Go]设计模式-工厂模式 (2)

然后编写一个单元测试来检验我们的代码:

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 关系图:

[Design Pattern With Go]设计模式-工厂模式

代码设计

抽象产品和具体产品的定义与工厂方法类似:

抽象产品

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") } } 小结

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywjjs.html