用乙個字典儲存beanname和資源
初始化時先將beanname和資源註冊到字典中
然後用乙個dscriptor類根據beanname動態請求資源,從而實現控制反轉
# -*- coding:utf-8 -*-
import os
class
beanfactory:
""" python版控制反轉
context: 儲存bean的名字和對應的類或者值的字典
allowrepalce: 是否允許替換已經注入的bean
"""def__init__
(self,allowreplace=false):
"""建構函式
allowreplace:是否允許替換已經注入的bean
"""self.context = {}
self.allowreplace = allowreplace
defsetbean
(self,beanname,resource,*args,**kwargs):
ifnot self.allowreplace:
assert
not beanname in self.context,"該beanfactory不允許重複注入%r,請修改beanname" % beanname
defcall
():"""定義乙個函式閉包,如果注入的resource是可呼叫型別,就將*args和**kwargs傳入並呼叫該函式,然後將返回值返回
如果是乙個不可呼叫物件,就直接返回
"""if callable(resource):
return resource(*args,**kwargs)
else:
return resource
#將call閉包與beanname建立對映
self.context[beanname]=call
def__getitem__
(self,beanname):
"""過載__getitem__方法,使得beanfactory支援使用獲取beanname對應的註冊的資源
"""try:
# 從context字典中取出beanname對應的資源
resource = self.context[beanname]
except keyerror:
raise keyerror("%r 未註冊" % beanname)
# 返回閉包函式呼叫後的結果
return resource()
defnoassertion
(obj):
return
true
defisinstanceof
(*classes):
deftest
(obj):
return isinstance(obj, classes)
return test
defhasattributes
(*attributes):
deftest
(obj):
for each in attributes:
ifnot hasattr(obj, each): return
false
return
true
return test
defhasmethods
(*methods):
deftest
(obj):
for each in methods:
try:
attr = getattr(obj, each)
except attributeerror:
return
false
ifnot callable(attr): return
false
return
true
return test##
#descriptor就是一類實現了__get__(), __set__(), __delete__()方法的物件
#若乙個類的成員是descriptor,在訪問它的值時是通過__get__()函式訪問的
#用這個特性實現在訪問乙個類的成員時自動到beanfactory中請求對應的資源
class
requiredresource
(object):
def__init__
(self, beanname, assertion=noassertion):
self.beanname = beanname
self.assertion = assertion
def__get__
(self, obj, t):
#每次訪問descriptor時都會呼叫__get__方法
return self.result # <-- .操作符會自動呼叫__getattr__
def__getattr__
(self, name):
assert name == 'result', "unexpected attribute request other then 'result'"
self.result = self.request()
return self.result
defrequest
(self):
assert self.assertion(obj), \
"the value %r of %r does not match the specified criteria" \
% (obj, self.feature)
return obj
class
component
(object):
"symbolic base class for components"
class
bar(component):
# hasmethods是乙個閉包函式,傳入requiredresource後用於檢查'console'
# 對應的註冊的那個feature是否有'writeline'方法
# isinstanceof(str) 是乙個閉包,傳入requiredresource後會被呼叫,用於
# isinstanceof(str) 是乙個閉包,傳入requiredresource後會被呼叫,用於
# 檢查'currentuser'對應的資源是否是乙個字串
# requiredfeatuire是desciptor,每次訪問descriptor(即實現了__get__的類),都會先經過__get__函式。
con = requiredresource('console', hasmethods('writeline'))
user = requiredresource('currentuser', isinstanceof(str))
flist = requiredresource('show_dir',isinstanceof(list))
def__init__
(self):
self.x = 0
defprintyourself
(self):
self.con.writeline('-- bar instance --')
self.con.writeline('title: %s' % self.title)
self.con.writeline('user: %s' % self.user)
self.con.writeline('x: %d' % self.x)
for f in self.flist:
self.con.writeline(f)
class
betterconsole
(component):
def__init__
(self, prefix=''):
self.prefix = prefix
defwriteline
(self, s):
lines = s.split('\n')
for line in lines:
if line:
print(self.prefix, line)
else:
print
defgetcurrentuser
():return os.getenv('username') or
'some user'
# username is platform-specific
defshowdir
():return os.listdir()
if __name__ == '__main__':
print('\n*** ioc demo ***')
#provide(feature,provider,*args,**kwargs) feature是要生成的物件的父類型別 provider是要注入的子類或者值
bar = bar()
bar.printyourself()
IoC控制反轉
首先假設有乙個需求,類business需要呼叫類dependency的方法f 1 按照日常的做法,得到下面的 類dependency public class dependency 類business public class business public void dosomething 2 對...
IOC 控制反轉
ioc是物件導向程式設計中的一種設計原則,可以借助 第三方 來減低計算機 之間的 耦合度 其中最常見的方式叫做依賴注入 dependency injection,簡稱di 還有一種方式叫 依賴查詢 dependency lookup 通過控制反轉,物件在被建立的時候,由乙個調控系統內所有物件的外界實...
IOC 控制反轉
想說說ioc inversion of control,控制反轉 這是spring的核心,貫穿始終。所謂ioc,對於spring框架來說,就是由spring來負責控制物件的生命週期和物件間的關係。這是什麼意思呢,舉個簡單的例子,我們是如何找女朋友的?常見的情況是,我們到處去看 有長得漂亮身材又好的m...