一、總線
總線是計(jì)算機(jī)各種功能部件或者設(shè)備之間傳送數(shù)據(jù)丢氢、控制信號(hào)等信息的公共通信解決方案之一∫丫桑現(xiàn)假設(shè)有如下場(chǎng)景:某中央處理器(CPU)通過(guò)某種協(xié)議總線與一個(gè)信號(hào)燈相連,信號(hào)燈有64種顏色可以設(shè)置撒妈,中央處理器上運(yùn)行著三個(gè)線程恢暖,都可以對(duì)這個(gè)信號(hào)燈進(jìn)行控制,并且可以獨(dú)立設(shè)置該信號(hào)燈的顏色狰右。抽象掉協(xié)議細(xì)節(jié)(用打印表示)杰捂,如何實(shí)現(xiàn)線程對(duì)信號(hào)等的控制邏輯。
加線程鎖進(jìn)行控制棋蚌,無(wú)疑是最先想到的方法嫁佳,但各個(gè)線程對(duì)鎖的控制挨队,無(wú)疑加大了模塊之間的耦合。下面蒿往,我們就用設(shè)計(jì)模式中的單例模式盛垦,來(lái)解決這個(gè)問(wèn)題。
什么是單例模式瓤漏?單例模式是指:保證一個(gè)類(lèi)僅有一個(gè)實(shí)例腾夯,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。具體到此例中蔬充,總線對(duì)象挽铁,就是一個(gè)單例寒锚,它僅有一個(gè)實(shí)例,各個(gè)線程對(duì)總線的訪問(wèn)只有一個(gè)全局訪問(wèn)點(diǎn),即惟一的實(shí)例坷剧。
Python代碼如下:
#encoding=utf8
import threading
import time
#這里使用方法__new__來(lái)實(shí)現(xiàn)單例模式
class Singleton(object):#抽象單例
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **kw)
return cls._instance
#總線
class Bus(Singleton):
lock = threading.RLock()
def sendData(self,data):
self.lock.acquire()
time.sleep(3)
print "Sending Signal Data...",data
self.lock.release()
#線程對(duì)象,為更加說(shuō)明單例的含義闰挡,這里將Bus對(duì)象實(shí)例化寫(xiě)在了run里
class VisitEntity(threading.Thread):
my_bus=""
name=""
def getName(self):
return self.name
def setName(self, name):
self.name=name
def run(self):
self.my_bus=Bus()
self.my_bus.sendData(self.name)
if __name__=="__main__":
for i in range(3):
print "Entity %d begin to run..."%i
my_entity=VisitEntity()
my_entity.setName("Entity_"+str(i))
my_entity.start()
運(yùn)行結(jié)果如下:
Entity 0 begin to run...
Entity 1 begin to run...
Entity 2 begin to run...
Sending Signal Data... Entity_0
Sending Signal Data... Entity_1
Sending Signal Data... Entity_2
在程序運(yùn)行過(guò)程中涕蜂,三個(gè)線程同時(shí)運(yùn)行(運(yùn)行結(jié)果的前三行先很快打印出來(lái)),而后分別占用總線資源(后三行每隔3秒打印一行)皿哨。雖然看上去總線Bus被實(shí)例化了三次浅侨,但實(shí)際上在內(nèi)存里只有一個(gè)實(shí)例。
二证膨、單例模式
單例模式是所有設(shè)計(jì)模式中比較簡(jiǎn)單的一類(lèi)如输,其定義如下:Ensure a class has only one instance, and provide a global point of access to it.(保證某一個(gè)類(lèi)只有一個(gè)實(shí)例,而且在全局只有一個(gè)訪問(wèn)點(diǎn))
三央勒、單例模式的優(yōu)點(diǎn)和應(yīng)用
單例模式的優(yōu)點(diǎn)
1不见、由于單例模式要求在全局內(nèi)只有一個(gè)實(shí)例,因而可以節(jié)省比較多的內(nèi)存空間崔步;
2稳吮、全局只有一個(gè)接入點(diǎn),可以更好地進(jìn)行數(shù)據(jù)同步控制井濒,避免多重占用灶似;
3、單例可長(zhǎng)駐內(nèi)存瑞你,減少系統(tǒng)開(kāi)銷(xiāo)酪惭。
單例模式的應(yīng)用舉例
1、生成全局惟一的序列號(hào)者甲;
2春感、訪問(wèn)全局復(fù)用的惟一資源,如磁盤(pán)虏缸、總線等鲫懒;
3纺铭、單個(gè)對(duì)象占用的資源過(guò)多,如數(shù)據(jù)庫(kù)等刀疙;
4舶赔、系統(tǒng)全局統(tǒng)一管理,如Windows下的Task Manager谦秧;
5竟纳、網(wǎng)站計(jì)數(shù)器。
四疚鲤、單例模式的缺點(diǎn)
1锥累、單例模式的擴(kuò)展是比較困難的;
2集歇、賦于了單例以太多的職責(zé)桶略,某種程度上違反單一職責(zé)原則(六大原則后面會(huì)講到);
3、單例模式是并發(fā)協(xié)作軟件模塊中需要最先完成的诲宇,因而其不利于測(cè)試际歼;
4、單例模式在某種情況下會(huì)導(dǎo)致“資源瓶頸”姑蓝。