Factory patterns trong golang
February 22, 2018
design pattern
Golang
Factory patterns là một design pattern mà hầu như tất cả các dự án đều sử dụng. Nếu bạn đã từng biết đến các khái niệm như interface hay implements thì chắc hẳn design pattern này đã ko còn gì xa lạ.
Để tạo ra những project code cleaner
thì design patterns
rõ ràng không thể thiếu trong mọi tư duy của developer. Hôm nay mình sẽ giới thiệu và đi xâu vào chi tiết về factory patterns trong golang.
Mô tả về factory patterns
Không giống các ngôn ngữ khác, Go ko sử dụng class mà được tạo dựng các object thông qua struct và interface
. các lớp interface thường là định hướng trước đối tượng và sẽ có nhiều cách thức để implements 1 interface.
Một ví dụ đơn giản, bạn có 1 đối tượng động vật tương tự như là 1 interface. từ lớp động vật đó bạn có thể tạo ra 1 động vật cụ thể như con chó, con mèo, con gà, … Các implements này nó nhiệm vụ thực thi và mô tả chi tiết 1 lớp interface đã được định nghĩa. Trong ứng dụng của bạn nếu nó phát triển mở rộng buộc lòng bạn phải làm quen với pattern này. Hãy tưởng tượng có một interface động vật. Bạn cũng chưa rõ ràng được sử dụng động vật gì, tuy nhiên động vật nào cũng có chân, tay, mắt, mũi, … Sau khi implements con chó thay cho interface động vật thì các phương thức chân, tay, mắt, mũi sẽ được định hình rõ hơn và cụ thể hơn.
Ví dụ đơn giản
Để mô tả chi tiết hơn mình sẽ khởi tạo 1 factory pattern. Giả xử mình có interface animal
type Animal interface {
run()
}
Sau khi có interface mình cần tạo thêm 1 implements cho interface trên
type dog struct {
name: string
age: int
}
func (d *dog) run() {
// todo something
}
và bây giờ việc cần làm là làm thế nào để kết hợp interface và struct
func NewDog() Animal {
return dog {
name: husky,
age: 2
}
}
Method khởi tạo trên có ý nghĩa khởi tạo 1 động vật các bạn có thể thấy nó return 1 interface và kết quả return chính là struct của interface đó.
Sử dụng trong các methods các bạn có thể gộp lại và làm như sau
type Animal interface {
run()
}
type dog struct {
name: string
age: int
}
func (d *dog) run() {
// todo something
fmt.Printf("Hi, Hello my name %s", d.name)
}
// Factory function
func NewDog() Animal {
return dog {
name: husky,
age: 2
}
}
func ActionAnimal(a Animal) {
a.run()
}
func main () {
dog := NewDog()
ActionAnimal(dog)
}
// Out put
Hi, Hello husky
Multiple implementations
Khi return về 1 interface, điều đó có nghĩa là chúng ta có thể tạo nhiều những factory function với nhiều implementations khác nhau.
vẫn với các ví dụ ở trên tuy nhiên bây giờ mình sẽ tạo ra 1 implementation là cat
type cat struct {
name: string
age: int
}
func (c *cat) run() {
// todo something
fmt.Printf("Hi, %s is %s year old", c.name, c.age)
}
// Factory function
func NewCat() Animal {
return cat {
name: tom,
age: 2
}
}
func main () {
dog := NewDog()
cat := NewCat()
ActionAnimal(dog)
ActionAnimal(cat)
}
Kết luận
Trong các project factory patterns là rất cần thiết, thay vì xử dụng trực tiếp các struct. Các bạn hoàn toàn có thể tạo ra các interface. Điều đó có nghĩa tất cả các cấu trúc trong project của các bạn được giao tiếp với nhau thông qua bởi các interface. Điều này giúp project của các bạn sạch sẽ và tối ưu hơn. Đôi khi bạn cần phải mở rộng ứng dụng của mình lên factory patterns sẽ đảm bảo cho code logic của bạn ko hề bị thay đổi. Việc cần làm là hãy viết các implementations khác để tối ưu hơn cho project của mình.
Hi vọng bài viết phần nào mang lại kiến thức bổ ích cho các bạn.