Prototype Pattern là gì?
Wikipedia định nghĩa prototype Pattern như sau:
The prototype pattern is a creational design pattern in software development. It is used when the type of objects to create is determined by a prototypical instance, which is cloned to produce new objects
Chúng ta có thể hiểu nôm na là Prototype pattern sẽ tạo ra một object mới bằng cách copy, object mới sẽ mang đầy đủ đặc tính của object ban đầu, và chúng ta có thể thay đổi object mới mà không ảnh hưởng gì đến object ban đầu
Prototype Pattern được sử dụng khi nào?
- Được dùng khi việc tạo một object tốn nhiều chi phí và thời gian trong khi bạn đã có một object tương tự tồn tại.
- Muốn truyền đối tượng vào một hàm nào đó để xử lý, thay vì truyền đối tượng gốc có thể ảnh hưởng dữ liệu thì ta có thể truyền đối tượng sao chép.
- Ẩn độ phức tạp của việc khởi tạo đối tượng từ phía Client.
- ...
Cài đặt Prototype Pattern
Hình ảnh minh hoa các thành phần của Prototype Pattern
Một Prototype Pattern gồm các thành phần cơ bản sau:
- Prototype : khai báo một class, interface hoặc abtract class cho việc clone chính nó.
- ConcretePrototype : phần này sẽ implement cho method clone được khai báo ở interface
- Client : có thể copy bất kì object nào thông qua phương thức clone
Ví dụ demo
Một công ty bất động sản muốn xây dựng các ngôi nhà liền kề giống nhau, mỗi ngôi nhà bao gồm các thông tin: số lượng phòng ngủ (bedroom), phòng khách (living room). Tùy vào nhu cầu của khách mua nhà mà số lượng phòng ngủ hay phòng khách có thể thay đổi được
Cách làm này được minh họa như sau:
- Đầu tiên chúng ta định nghĩa interface
iHouse
- Tiếp theo, chúng ta sẽ tạo một đối tượng
normalHouse
implement interfaceiHouse
- Sau đó, mỗi khi muốn xây ngôi nhà mới, chỉ việc clone() từ ngôi nhà chuẩn đã tạo ban đầu. Tùy theo, nhu cầu của mỗi khách hàng có thể thay đổi số lượng phòng lại cho phù hợp (SetLivingRoom(), SetBedRoom())
Triển khai
iHouse.go
: Định nghĩa iHouse interface với danh sách method
package house
type iHouse interface {
Print()
SetLivingRoom(int)
SetBedRoom(int)
Clone() iHouse
}
normal_house.go
package house
import "fmt"
type NormalHouse struct {
LivingRoom int
BedRoom int
}
func (h *NormalHouse) Print() {
fmt.Printf("%d living room - %d bed room\n", h.LivingRoom, h.BedRoom)
}
func (h *NormalHouse) SetLivingRoom(room int) {
h.LivingRoom = room
}
func (h *NormalHouse) SetBedRoom(room int) {
h.BedRoom = room
}
func (h *NormalHouse) Clone() iHouse {
return &NormalHouse{
LivingRoom: h.LivingRoom,
BedRoom: h.BedRoom,
}
}
Ở đây chúng ta khai báo đối tượng NormalHouse với 2 thuộc tính : LivingRoom, BedRoom
Đồng thời khai báo tất cả các phương thức để inplement interface iHouse
main.go
package main
import (
"prototype-pattern/house"
)
func main() {
// Tạo 1 ngôi nhà với 1 phòng khách và 1 phòng ngủ
normalHouse := house.NormalHouse {
LivingRoom : 1,
BedRoom : 1,
}
normalHouse.Print() // 1 living room - 1 bed room
// Clone 1 ngôi nhà từ ngôi nhà đã tạo từ trước
normalHouseClone := normalHouse.Clone()
normalHouseClone.Print() // 1 living room - 1 bed room
// Thay đôi số lượng phòng khách và phòng ngủ của ngôi nhà vừa clone
normalHouseClone.SetBedRoom(2)
normalHouseClone.SetLivingRoom(3)
normalHouseClone.Print() // 3 living room - 2 bed room
// Kiểm tra lại ngôi nhà ban đầu
normalHouse.Print() // 1 living room - 1 bed room
}
File main.go
đóng vai trò như là một client, ở đây chúng ta sẽ tiến hành tạo ra một ngôi nhà chuẩn ban đầu normalHouse với (1 living room, 1 bed room)
Tiếp theo, nếu chúng ta muốn tạo ra nhưng ngôi nhà khác (normalHouseClone) từ ngôi nhà ban đầu normalHouse, thì chỉ việc gọi phương thức Clone()
Trường hợp muốn thay đổi số lượng living room, bed room, chúng ta chỉ cần truyền số lượng mong muốn vào phương thức SetBedRoom(), SetLivingRoom()
Kết quả đạt được
1 living room - 1 bed room
1 living room - 1 bed room
3 living room - 2 bed room
1 living room - 1 bed room
Ưu và nhược điểm của pattern này
Ưu điểm
- Có thể dễ dàng sao chép 1 đối tượng mà không cần quan tâm đến class cụ thể
- Có thể loại bỏ các đoạn code lặp đi lặp lại khi khởi tạo đối tượng
- Có thể tạo ra các đối tượng phức tạp một cách thuận tiện và nhanh chóng
- Đây có thể coi là một giải pháp cho kế thừa
Nhược điểm
- Nếu object có tham chiếu hoặc kế thừa từ các object khác. Clone thì dễ, nhưng không biết mức độ ảnh hưởng tới đâu. Nếu object clone có dây mơ rễ má nhiều chỗ -> rất dễ trở thành một đám tơ vò.
Bình luận