美文网首页
Python抽象类、接口、依赖注入

Python抽象类、接口、依赖注入

作者: BenjaminY | 来源:发表于2019-03-21 09:52 被阅读0次

    首先,我们必须明确的一点是:python里无接口类型,定义接口只是一个人为规定,在编程过程自我约束

    接口

    python的类是可以写任意个方法的
    定义一个接口对继承类进行约束,接口里有什么方法,继承类就必须有什么方法,接口中不能有任何功能代码

    class Interface:
         
        def f1(self):
            '''
            to do something
            :return:
            '''
     
    class Something(Interface):
         
        def f1(self):
            print('to do something...')
         
        def f2(self):
            print('to do other..')
    

    在其他的语言里,比如Java,继承类没有重写接口方法是会报错的,而在python里不会,就是因为python没这个类型,所以只是在我们编程过程的一个规定,以I开头的类视为接口

    class IOrderRepository:
     
        def fetch_one_by(self,nid):
            raise Exception('子类中必须实现该方法')
     
    class Something(IOrderRepository):
     
        def fet_one_by(self,nid):
            print('查查查数据....')
    

    抽象类,抽象方法

    抽象类,可以说是类和接口的混合体,既可以定义常规方法,也可以约束子类的方法(抽象方法)

    import abc
     
    #抽象类
    class Foo(metaclass=abc.ABCMeta):
     
        def f1(self):
            print('f1')
     
        #抽象方法
        @abc.abstractmethod
        def f2(self):
            '''
            打印f2
            '''
     
    class Bar(Foo):
     
        def f2(self):
            print('f2')
     
        def f3(self):
            print('f3')
     
    b = Bar()
    b.f1()
    b.f2()
    b.f3()
     
    

    依赖注入

    首先我们先看一个普通的类:

    class Foo:
        def __init__(self):
            self.name = 'alex'
         
        def f1(self):
            print(self.name)
    

    首先要明确的是,在python里,一切事物皆为对象
    而所有的类都是对象,默认是由type创建
    创建类的执行流程:

    遇到class关键词,执行type的init方法,创建Foo类这个对象
    遇实例化对象(obj=Foo()),执行type里的call方法
    在call方法里调用Foo类的new方法(负责创建对象)
    执行Foo类的init方法(初始化)
    了解其中的原理,我们就可以在call里面大做文章啦

    class MyType(type):
     
        def __call__(cls,*args,**kwargs):
            obj = cls.__new__(cls,*args,**kwargs)
            print('在这里面..')
            print('==========================')
            print('来咬我呀')
            obj.__init__(*args,**kwargs)
            return obj
     
     
    class Foo(metaclass=MyType):
     
        def __init__(self):
            self.name = 'alex'
     
    f = Foo()
    print(f.name)
    

    如果要熟练应用依赖注入,我还要弄懂一个概念,那就是组合:组合的目的就是解耦,减少依赖性,原来以某个具体的值或对象传入到内部改成以参数的形式传入

    比如:在实例Bar对象时,封装Foo对象,实例Foo对象封装Head对象,就用参数的形式传入到构造方法里

    class Mapper:
     
        #在字典里定义依赖注入关系
        __mapper_relation = {}
     
        #类直接调用注册关系
        @staticmethod
        def register(cls,value):
            Mapper.__mapper_relation[cls] = value
     
        @staticmethod
        def exist(cls):
            if cls in Mapper.__mapper_relation:
                return True
            return False
     
        @staticmethod
        def get_value(cls):
            return Mapper.__mapper_relation[cls]
     
    class MyType(type):
        def __call__(cls,*args,**kwargs):
            obj = cls.__new__(cls,*args,**kwargs)
            arg_list = list(args)
            if Mapper.exist(cls):
                value = Mapper.get_value(cls)
                arg_list.append(value)
            obj.__init__(*arg_list,**kwargs)
            return obj
     
    class Head:
     
        def __init__(self):
            self.name = 'alex'
     
    class Foo(metaclass=MyType):
     
        def __init__(self,h):
            self.h = h
     
        def f1(self):
            print(self.h)
     
    class Bar(metaclass=MyType):
     
        def __init__(self,f):
            self.f = f
     
        def f2(self):
            print(self.f)
     
    Mapper.register(Foo,Head())
    Mapper.register(Bar,Foo())
     
     
    if __name__ == '__main__':
        Mapper.register(Foo, Head())
        Mapper.register(Bar, Foo())
        head = Mapper.get_value(Foo)
        print('1111111')
        print(head)
        print(head.name)
        print('2222222')
        foo = Mapper.get_value(Bar)
        print(foo)
        print(foo.h.name)
        print('3333333')
        b = Bar()
        print(b.f)
        print(b.f.h.name)
    
    # 输出
    1111111
    <__main__.Head object at 0x00000000023F4F98>
    alex
    2222222
    <__main__.Foo object at 0x00000000023FF080>
    alex
    3333333
    <__main__.Foo object at 0x00000000023FF080>
    alex
    
    

    相关文章

      网友评论

          本文标题:Python抽象类、接口、依赖注入

          本文链接:https://www.haomeiwen.com/subject/bbifvqtx.html