一、什么是原型模式
原型模式允許一個對象再創建另外一個可定制的對象,根本無需知道任何如何創建的細節,工作原理是:通過將一個原型對象傳給那個要發動創建的對象,這個要發動創建的對象通過請求原型對象拷貝它們自己來實施創建。
原型模式用原型實例指定創建對象的種類,并通過拷貝這些原型創建新的對象。需要注意的關鍵字是,新的對象,類沒變。
原型模式用于當大量操作或操作復雜對象時,性能優勢將會很明顯。
它主要面對的問題是:“某些結構復雜的對象”的創建工作;由于需求的變化,這些對象經常面臨著劇烈的變化,但是他們卻擁有比較穩定一致的接口。
二、原型模式的結構
角色 | 含義 |
---|---|
抽象原型 | 這是一個抽象角色,通常由一個抽象類實現。此角色給出所有的具體原型類所需的接口 |
具體原型 | 被復制的對象。此角色需要實現抽象的原型角色所要求的接口 |
客戶端 | 客戶端類向原型管理器提出創建對象的請求 |
三、原型模式的代碼實現
python實現
class Prototype(object):
def __init__(self, value='default', **attrs) -> None:
self.value = value
self.__dict__.update(attrs)
def clone(self, **attrs):
"""Clone a prototype and update inner attributes dictionary"""
obj = self.__class__(**self.__dict__)
obj.__dict__.update(attrs)
return obj
class PrototypeDispatcher:
def __init__(self):
self._objects = {}
def get_objects(self):
"""Get all objects"""
return self._objects
def register_object(self, name, obj) -> None:
"""Register an object"""
self._objects[name] = obj
def unregister_object(self, name) -> None:
"""Unregister an object"""
del self._objects[name]
if __name__ == '__main__':
# 初始化一個原型
my_prototype = Prototype(value="test")
# 完全復制my_prototype的屬性
obj1 = my_prototype.clone()
# 繼承my_prototype并增加修改一些屬性
obj2 = my_prototype.clone(vlaue='test2')
# 繼承obj2 并增加修改一些屬性
obj3 = obj2.clone(value='test3', is_checked=True)
# PrototypeDispatcher更像是一個管理者,管理所有的原型對象
dispatcher = PrototypeDispatcher()
dispatcher.register_object('object1', obj1)
dispatcher.register_object('object2', obj2)
dispatcher.register_object('object3', obj3)
for n, p in dispatcher.get_objects().items():
print({n: p.value})
golang實現
type Student struct {
name string
age int
sex string
}
func (s *Student) SetStudentInfo(name string, age int, sex string) {
s.name = name
s.age = age
s.sex = sex
}
func (s *Student) SetName(name string) {
s.name = name
}
func (s *Student) PrintInfo() {
fmt.Printf("學生姓名: %s, 年齡: %d, 性別: %s\n", s.name, s.age, s.sex)
}
func (s *Student) Clone() *Student {
return &Student{
name: s.name,
age: s.age,
sex: s.sex,
}
}
func main() {
s1 := &Student{}
s1.SetStudentInfo("張三", 18, "男")
s1.PrintInfo()
s2 := s1.Clone()
s2.SetName("李四")
s2.PrintInfo()
}
四、原型模式的優缺點
優點
- 原型模式用于創建復雜的或者耗時的實例
- 復制一個已經存在的實例使程序運行更高效
- 對于工廠模式,原型模式減少了子類的構建
缺點
- 需要為每個類實現一個克隆方法,該方法位于類的內部,當對已有類進行改造的時候,需要修改代碼,違反了開閉原則
- 深拷貝與淺拷貝的風險,容易出錯
五、原型模式的應用場景
原型模式多用于創建大對象,或初始化繁瑣的對象。
如游戲中的背景,地圖。web中的畫布等等
以下場景適用:
- 一是類初始化需要消化非常多的資源,這個資源包括數據、硬件資源等;
- 二是通過 new 產生一個對象需要非常繁瑣的數據準備或訪問權限,則可以使用原型模式;
- 三是一個對象需要提供給其他對象訪問,而且各個調用者可能都需要修改其值時,可以考慮使用原型模式拷貝多個對象供調用者使用。
在實際項目中,原型模式很少單獨出現,一般是和工廠方法模式一起出現,通過 clone的方法創建一個對象,然后由工廠方法提供給調用者。