python教程14、設計模式
設計模式是什麼?
設計模式是經過總結、優化的,對我們經常會碰到的一些程式設計問題的可重用解決方案。一個設計模式並不像一個類或一個庫那樣能夠直接作用於我們的程式碼。反之,設計模式更為高階,它是一種必須在特定情形下實現的一種方法模板。設計模式不會繫結具體的程式語言。一個好的設計模式應該能夠用大部分程式語言實現(如果做不到全部的話,具體取決於語言特性)。最為重要的是,設計模式也是一把雙刃劍,如果設計模式被用在不恰當的情形下將會造成災難,進而帶來無窮的麻煩。然而如果設計模式在正確的時間被用在正確地地方,它將是你的救星。
這裡列舉了三種最基本的設計模式:
1、結構化模式,通常用來處理實體之間的關係,使得這些實體能夠更好地協同工作。
外觀模式(Facade); 介面卡模式(Adapter); 代理模式(Proxy); 裝飾模式(Decorator); 橋模式(Bridge); 組合模式(Composite); 享元模式(Flyweight)。
2、建立模式,提供例項化的方法,為適合的狀況提供相應的物件建立方法。
簡單工廠模式(Simple Factory); 工廠方法模式(Factory Method); 抽象工廠模式(Abstract Factory); 建立者模式(Builder); 原型模式(Prototype); 單例模式(Singleton)。
3、行為模式,用於在不同的實體建進行通訊,為實體之間的通訊提供更容易,更靈活的通訊方法。
模板方法模式(Template Method); 觀察者模式(Observer); 狀態模式(State); 策略模式(Strategy); 職責鏈模式(Chain of Responsibility); 命令模式(Command); 訪問者模式(Visitor); 調停者模式(Mediator); 備忘錄模式(Memento); 迭代器模式(Iterator); 直譯器模式(Interpreter)。
我們為什麼要使用設計模式?
從理論上來說,設計模式是對程式問題比較好的解決方案。無數的程式設計師都曾經遇到過這些問題,並且他們使用這些解決方案去處理這些問題。所以當你遇到同樣的問題,為什麼要去想著建立一個解決方案而不是用現成的並且被證明是有效的呢?
單例模式:
單例,顧名思義單個例項,單利模式存在的目的是保證當前記憶體中僅存在單個例項,避免記憶體浪費
對於Python單例模式,建立物件時不能再直接使用:obj = Foo(),而應該呼叫特殊的方法:obj = Foo.singleton() 。
方法一、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class
Instance:
__instance
=
None
# 私有類屬性
def
__init__(
self
):
self
.name
=
'linux'
self
.passwd
=
'kkkkk'
@staticmethod
def
get_instance():
if
not
Instance.__instance:
# 如果私有類屬性為空的話,建立一個例項
Instance.__instance
=
Instance()
return
Instance.__instance
# 不為空的話,直接返回一個例項
obj1
=
Instance.get_instance()
# 執行靜態方法,建立一個例項賦值給obj1
obj2
=
Instance.get_instance()
# 執行靜態方法,將私有類屬性儲存的物件賦值給obj2
print
(obj1)
# <__main__.Instance object at 0x0000021AEDF56048>
print
(obj2)
# <__main__.Instance object at 0x0000021AEDF56048>
|
方法二、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class
Foo:
instance
=
None
def
__init__(
self
,name):
self
.name
=
name
@classmethod
def
get_instance(
cls
):
if
cls
.instance:
return
cls
.instance
else
:
obj
=
cls
(
"python"
)
cls
.instance
=
obj
return
obj
obj
=
Foo.get_instance()
print
(obj)
obj1
=
Foo.get_instance()
print
(obj1)
|
方法三、
1 2 3 4 5 6 7 8 9 10 11 |
class
Singleton():
def
__new__(
cls
,
*
args,
*
*
kwargs):
if
not
hasattr
(
cls
,
'_instance'
):
cls
._instance
=
super
(Singleton,
cls
).__new__(
cls
,
*
args,
*
*
kwargs)
return
cls
._instance
class
A(Singleton):
pass
a
=
A()
b
=
A()
print
(a
is
b)
|
方法四、
1 2 3 4 5 6 7 8 9 10 11 12 |
class
Singleton(
type
):
def
__call__(
cls
,
*
args,
*
*
kwargs):
if
not
hasattr
(
cls
,
'_instance'
):
cls
._instance
=
super
(Singleton,
cls
).__call__(
*
args,
*
*
kwargs)
return
cls
._instance
class
A(metaclass
=
Singleton):
# __metaclass__ = Singleton
pass
a
=
A()
b
=
A()
print
(a
is
b)
|
方法五、
1 2 3 4 5 6 7 8 9 10 |
class
SingMetaclass(
type
):
def
__call__(
self
,
*
args,
*
*
kwargs):
if
not
hasattr
(
self
,
'instance'
):
# self.instance = super(SingMetaclass, cls).__new__(cls, name, base, attrs)
# self.instance = self.__new__(self, *args, **kwargs) # 下面這種方式也行,但是沒有註釋掉的好理解
self
.instance
=
super
().__call__(
*
args,
*
*
kwargs)
return
self
.instance
class
A(metaclass
=
SingMetaclass):
pass
|
後續用到其他模式再進行新增!!
總結
在本文中,我只列舉了幾個我再程式設計中覺得十分重要的設計模式來講,除此之外還有很多設計模式需要學習。如果你對其他的設計模式感興趣,維基百科的設計模式部分可以提供很多資訊。如果還嫌不夠,你可以看看四人幫的《設計模式:可複用面向物件軟體的基礎》一書,此書是關於設計模式的經典之作。
最後一件事:當使用設計模式時,確保你是用來解決正確地問題。正如我之前提到的,設計模式是把雙刃劍:如果使用不當,它們會造成潛在的問題;如果使用得當,它們則將是不可或缺的。