抽象工厂模式(Abstract Factory)
如果有看过上一篇工厂方法模式,这篇就更简单了.抽象工厂模式是工厂方法模式的进阶版,怎么个进阶法呢?
先来简单回顾下工厂方法模式核心代码:
//Food 食物接口
type Food interface {
Eat()
}
//....省略....
//工厂
type Factory interface {
NewFood(k FoodKind) Food //返回食物接口
}
我们Factory接口里面只有一个方法声明,如果我们再加一个呢或者多个呢?对,别怀疑,这个就是抽象工厂模式.
人平时吃五谷杂粮难免会生病,生病肯定就要吃药药.那就加个吃药药的方法声明.
//Food 食物接口
type Food interface {
Eat()
}
//Drug 药物接口
type Drug interface{
Take()
}
//....省略....
//工厂
type Factory interface {
NewFood() Food //返回食物接口
NewDrug() Drug //返回药物接口
}
很简单吧,就是多了一个NewDrug() Drug
其实这种接口大家肯定是见过类似的,打开源码文件types.go
// A FileInfo describes a file and is returned by Stat and Lstat.
type FileInfo interface {
Name() string // base name of the file
Size() int64 // length in bytes for regular files; system-dependent for others
Mode() FileMode // file mode bits
ModTime() time.Time // modification time
IsDir() bool // abbreviation for Mode().IsDir()
Sys() interface{} // underlying data source (can return nil)
}
这里FileInfo声明的几个方法,功能都是有关联性的,所以放在了一个interface里面.
在types_unix.go中基于unix平台的特性实现了FileInfo所有接口
在types_windows.go中基于windows平台特性实现了FileInfo所有接口
各个平台各自实现自己的功能,用这种方式解耦和,这不就是设计模式强调的开放闭合原则的体现吗?
抽象工厂模式
- 好处:可以在内部对相关联的多个产品共同管理,而不必引入多个新的类.
- 坏处:当增加一个新的产品类时,例如这里再加个Water interface,所有的工厂类相关的实现都要进行改动.
上面不懂,没关系,看代码
package abstract
import (
"fmt"
)
//Food -- 抽象的食物接口
type Food interface {
Eat()
}
//Drug -- 抽象的药物接口
type Drug interface {
Take()
}
//Factory 负责生产药物类和食物类
type Factory interface {
NewFood() Food
NewDrug() Drug
}
//-----Food 实现结构体----
type meat struct { // 肉
}
func (t meat) Eat() {
fmt.Println("Eat meat")
}
type fruit struct { //水果
}
func (t fruit) Eat() {
fmt.Println("Eat fruit")
}
// -----Drug 实现结构体-----
type feverdrug struct { //发烧药
}
func (t feverdrug) Take() {
fmt.Println("Take fever drug")
}
type colddrug struct { //感冒药
}
func (t colddrug) Take() {
fmt.Println("Take cold drug")
}
//------ Factory 实现结构体 ------
type FirstFactory struct { // 第一个工厂
}
func (t *FirstFactory) NewFood() Food {
return meat{}
}
func (t *FirstFactory) NewDrug() Drug {
return feverdrug{}
}
type SecondFactory struct { // 第二个工厂
}
func (t *SecondFactory) NewFood() Food {
return fruit{}
}
func (t *SecondFactory) NewDrug() Drug {
return colddrug{}
}
第一个工厂负责肉和发烧药的生成
第二个工厂负责水果和感冒药的生成
不管第一个厂和第二个厂内部实现如何不一样,都是对Factory接口的实现类型而已.
- 调用
func main(){
fmt.Println("抽象工厂模式")
first := &abstract.FirstFactory{} //这里用的&符号,因为只实现了指针类型
first.NewFood().Eat()
first.NewDrug().Take()
second := &abstract.SecondFactory{}
second.NewFood().Eat()
second.NewDrug().Take()
}
- 结果
抽象工厂模式
Eat meat
Take fever drug
Eat fruit
Take cold drug总结
工厂相关的模式其实就是套模板
type Product1 interface {
}
type Product2 interface {
}
type Factory interface{
Create1() Product1
Create2() Product2
}
用一个Factory接口内部的函数声明Create*() Product*,创建其他接口类型,这也就是为什么要叫创建型模型的原因.
怎么学习设计模式?
之前刚开学习代码的时候,看过一次(就看了两个),完全看不懂,也就放弃了.后来工作3年后,又强制自己去看了一次(也没看完,零零散散),开始有点理解,但是又觉得罗里吧嗦的,好烦,又不想看了.突然有一天觉得,好像工作好久了,然后大家都说设计模式好,不自觉的就想捡起来看下.但是迟迟没有下定决心去看.后来机缘巧合下,公司要求大家都去学习Go语言,从语言层次来说Go确实简单,但是怎么在实际项目中灵活运用,完全没思路.正好设计模式,就是结合语言特性,教你合理的运用语言,那还有啥好说的,干吧~~打工人
学完后对我的感触就是对语言的理解上,运用上更有大局观了.看别人源码的时候,知道别人为什么这么写,有点心有灵犀的感觉.
为了学习设计模式,前前后后反反复复看资料,练习不少于5遍(可能是基础确实比较差).为了写文章,把所有的模式都打了一遍草稿.最大的感触是:要理解它的"神",而非"形".就像小说里面讲的:练剑法的最高境界是无招胜有招,高手是不会拘泥招式的限制.
同时选择一个简单的语言去学习,也可以事半功倍.
建议: 第一次学习请先死记招式,并且归纳出自己的理解.最后学习完,你会发现,其实都是差不多的.
源码地址 :