刚学一点 Go,
除了能够使用别人写好的 modules,
为了程序码的可扩充性,也需要理解 Design Patterns。
今天搭配 Github 上的程序码来学习各种「工厂」的设计模式~
大一刚学 Java 时,学到一些 interface 的概念,
也接触到 Design Patterns 的书,
但实在难以理解制造出会叫的鸭子跟未来写网页、写应用程序的关联?
设计模式,是别人研究出来,怎麽样写程序能达到好扩充的方法。
因为需求会变动,
如果新增一个功能就要增加非常多行程序码,
或是新增程序码常常导致旧功能出错,
十分浪费时间心力。
我觉得学习 Design Patterns 不是一件容易的事,
运用到很多抽象化的概念。
而就算理解一个设计模式,
接下来要能够融会贯通的使用在适合的情境,除了经验也需要刻意留心。
本篇参考这个 Github repo 的程序码:Go 语言设计模式 来理解设计模式。
而这本 Gitbook 设计模式学习笔记 讲解前面几个模式也算是简单易懂,并附上类别图和程序码,值得参考。
注意 Go 里面没有 object / class,
这边如果提到物件通常是 Go 中 implement interface 的 struct
根据传入的参数回传指定物件
package main
import "fmt"
type Animal interface {
Say() string
}
func newAnimal(t int) Animal {
// 如果想增加不同动物,需要在这里改
// 不符合 SOLID 的 O(开放封闭原则)
if t == 1 {
return Dog{}
} else if t == 2{
return &Cat{}
}
return nil
}
type Cat struct {}
type Dog struct {}
func (*Cat) Say() string {
return "meow!"
}
func (Dog) Say() string {
return "bark!"
}
func main() {
a1 := newAnimal(1)
fmt.Println("type 1 Animal")
fmt.Println(a1.Say())
a2 := newAnimal(2)
fmt.Println("type 2 Animal")
fmt.Println(a2.Say())
}
规定一个工厂该有的样子(interface),要能够制造不同商品(instance)就各自去实现不同的工厂
repo 中的程序码以 Operator 来举例。04_factory_method
OperatorFactory
是工厂 interface,合格的工厂应该要实作一个会制造出 Operator
的 Create
method。
Operator
则是定义了 SetA
SetB
Result
三个 method。
SetA
SetB
都是对 struct OperatorBase
定义的 method,OperatorBase
中有 a b 两整数。
提醒 Go 中没有继承,就用 nested struct 达到类似效果:
type PlusOperator struct {
*OperatorBase
}
工厂产生的物件「有关联」
完整程序码:05_abstract_factory
DAOFactory
是抽象工厂的 interface,要实作这个工厂,底下就要使用 CreateOrderMainDAO()
与 CreateOrderDetailDAO()
分别实作两个子工厂 OrderMainDAO
与 OrderDetailDAO
。
这里就存有订单主纪录与详情纪录的抽象关系。
type OrderMainDAO interface {
SaveOrderMain()
}
type OrderDetailDAO interface {
SaveOrderDetail()
}
type DAOFactory interface {
CreateOrderMainDAO() OrderMainDAO
CreateOrderDetailDAO() OrderDetailDAO
}
RDB 工厂的实作环节,
首先先做一个 RDB 抽象工厂,
里面要去实作 使用 RDB 储存主纪录和详情纪录的实现方式。
XML 的工厂实作也一样,就是 method 里面的实作细节不同而已
// 使用 RDB 存主纪录
type RDBMainDAO struct{}
func (*RDBMainDAO) SaveOrderMain() {
fmt.Print("rdb main save\n")
}
// 使用 RDB 存详情纪录
type RDBDetailDAO struct{}
func (*RDBDetailDAO) SaveOrderDetail() {
fmt.Print("rdb detail save\n")
}
// RDB 的抽象工厂与实现
type RDBDAOFactory struct{}
func (*RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO {
return &RDBMainDAO{}
}
func (*RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO {
return &RDBDetailDAO{}
}
<<: Day 27 - 3D绘图篇 - 2D图片上面的3D物件是怎麽产生的? I - 成为Canvas Ninja ~ 理解2D渲染的精髓
>>: Day 28 - WooCommerce: 显示虚拟帐号付款资讯
阿嬷都看得懂的 style 标签怎麽用 昨天我们介绍了 CSS 选择器,所以终於知道该怎麽把独立收整...
Virtual Judge ZeroJudge 题意 输入比赛的分数总和及分差,输出两队分数 需要...
JavaScript型别 前面有说过JavaScript是动态型别,也就是说在执行时,变数会依照赋予...
照着前几天的逻辑今天来用python执行xgboost,刚开始一样先写score function方...
https://edm.bnext.com.tw/2021cpx/?utm_source=%E3%8...