Python实现IOC控制反转
思路:
用一个字典存储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
def setBean(self,beanName,resource,*args,**kwargs):
if not self.allowReplace:
assert not beanName in self.context,"该BeanFactory不允许重复注入%r,请修改beanName" % beanName
def call():
"""定义一个函数闭包,如果注入的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()
AppFactory = BeanFactory()
def NoAssertion(obj): return True
def IsInstanceOf(*classes):
def test(obj): return isinstance(obj, classes)
return test
def HasAttributes(*attributes):
def test(obj):
for each in attributes:
if not hasattr(obj, each): return False
return True
return test
def HasMethods(*methods):
def test(obj):
for each in methods:
try:
attr = getattr(obj, each)
except AttributeError:
return False
if not 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
def Request(self):
obj = AppFactory[self.beanName]
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后会被调用,用于
# 检查注册的'AppTitle'对应资源是否是一个字符串
# IsinstanceOf(str) 是一个闭包,传入RequiredResource后会被调用,用于
# 检查'CurrentUser'对应的资源是否是一个字符串
# RequiredFeatuire是desciptor,每次访问descriptor(即实现了__get__的类),都会先经过__get__函数。
con = RequiredResource('Console', HasMethods('WriteLine'))
title = RequiredResource('AppTitle', IsInstanceOf(str))
user = RequiredResource('CurrentUser', IsInstanceOf(str))
flist = RequiredResource('show_dir',IsInstanceOf(list))
def __init__(self):
self.X = 0
def PrintYourself(self):
self.con.WriteLine('-- Bar instance --')
# title 由 RequiredResource('AppTitle',IsInstanceOf(str))生成
#'AppTitle'对应的值在__main__代码块注册了一个值
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
def WriteLine(self, s):
lines = s.split('\n')
for line in lines:
if line:
print(self.prefix, line)
else:
print
def GetCurrentUser():
return os.getenv('USERNAME') or 'Some User' # USERNAME is platform-specific
def ShowDir():
return os.listdir()
if __name__ == '__main__':
print('\n*** IoC Demo ***')
#Provide(feature,provider,*args,**kwargs) feature是要生成的对象的父类类型 provider是要注入的子类或者值
AppFactory.setBean('AppTitle', 'Inversion of Control ...\n\n... The Python Way')
AppFactory.setBean('CurrentUser', GetCurrentUser)
AppFactory.setBean('Console', BetterConsole, prefix='-->') # <-- transient lifestyle
AppFactory.setBean('show_dir',ShowDir)
bar = Bar()
bar.PrintYourself()
Python实现IOC控制反转的更多相关文章
- 回顾Spirng ioc 控制反转
Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的.结合网上对Spring Ioc的理解,回顾一下自 ...
- 谈谈php里的IOC控制反转,DI依赖注入
理论 发现问题 在深入细节之前,需要确保我们理解"IOC控制反转"和"DI依赖注入"是什么,能够解决什么问题,这些在维基百科中有非常清晰的说明. 控制反转(In ...
- DI依赖注入/IOC控制反转
DI依赖注入# 啥都不说,直接上代码 <?php class UserController { private $user; function __construct(UserModel $us ...
- IoC实践--用Autofac实现MVC5.0的IoC控制反转方法
Autofac是一个.net平台下发性能还不错的IoC框架,利用它可以实现依赖注入和控制反转,使自己的软件模块之间的耦合性大大降低,让软件扩展.维护更加容易.控制反转(Inversion of Con ...
- IoC控制反转与DI依赖注入
IoC控制反转与DI依赖注入 IoC: Inversion of Control IoC是一种模式.目的是达到程序的复用.下面的两篇论文是对IoC的权威解释: InversionOfControl h ...
- Spring学习之Ioc控制反转(1)
开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...
- Spring学习之Ioc控制反转(2)
开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...
- Spring框架之IOC(控制反转)
[TOC] 第一章Spring框架简介 IOC(控制反转)和AOP(面向方面编程)作为Spring框架的两个核心,很好地实现了解耦合.所以,简单来说,Spring是一个轻量级的控制反转(IoC)和面向 ...
- Spring详解(二)------IOC控制反转
我相信提到 Spring,很多人会脱口而出IOC(控制反转).DI(依赖注入).AOP等等概念,这些概念也是面试官经常问到的知识点.那么这篇博客我们就来详细的讲解 IOC控制反转. ps:本篇博客源码 ...
随机推荐
- TypeScript 源码详细解读(1)总览
TypeScript 由微软在 2012 年 10 月首发,经过几年的发展,已经成为国内外很多前端团队的首选编程语言.前端三大框架中的 Angular 和 Vue 3 也都改用了 TypeScript ...
- Alodi:环境创建从未如此简单
一个满足你各种想象的快速方便生成临时环境的系统 在『Alodi:为了保密我开发了一个系统』文章中有讲到我们开发了一个系统用来快速生成临时测试环境,短短三个月已有数百个环境被创建,简化了工作,节省了时间 ...
- TensorFlow——学习率衰减的使用方法
在TensorFlow的优化器中, 都要设置学习率.学习率是在精度和速度之间找到一个平衡: 学习率太大,训练的速度会有提升,但是结果的精度不够,而且还可能导致不能收敛出现震荡的情况. 学习率太小,精度 ...
- 如何应用threejs实现立方体每个面用图片替换
var geometry = new THREE.BoxGeometry(200, 200, 200);var materialsbg = []; for (var i = 0; i < geo ...
- 数字任意组合 - gcd
链接:https://www.nowcoder.com/acm/contest/160/A来源:牛客网 题目描述有一个计数器,计数器的初始值为0,每次操作你可以把计数器的值加上a1,a2,...,an ...
- poj 2689 区间素数筛
The branch of mathematics called number theory is about properties of numbers. One of the areas that ...
- Spring Boot 事务的使用
Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactio ...
- 9.Super详解
super注意点: surper()是调用父类的构造方法,而且必须在构造方法的第一个 super必须只能出现在子类的方法或者构造方法中! super()和this()不能同时调用构造方法! Vs th ...
- ugui制作伸缩菜单
制作一个类似与这种格式的菜单,可以伸缩滑动的.今天正好项目需要用到类似功能,所以尝试了一下,做出如下的效果 虽然只是一个思路,但是可以扩展.声明一个object物体,为but,通过GetCompone ...
- 每天玩转3分钟 MyBatis-Plus - 6. select 用法
每天玩转3分钟 MyBatis-Plus - 1. 配置环境 每天玩转3分钟 MyBatis-Plus - 2. 普通查询 每天玩转3分钟 MyBatis-Plus - 3. 高级查询(一) 每天玩转 ...