zoukankan      html  css  js  c++  java
  • 项目设计原则

    开始之前需要引入一些项目设计知识,如接口,抽象方法抽象类,组合,程序设计原则等,个人理解项目的合理设计可增加其灵活性,降低数据之间的耦合性,提高稳定性,下面介绍一些预备知识 

    1. 接口

      其实py中没有接口这个概念。要想实现接口的功能,可以通过主动抛出异常来实现

      接口作用:对派生类起到限制的作用

    例:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    """
    接口,python中的接口,通过在父类中主动抛出异常实现
    接口的作用:起到了限制的作用
    """
    
    class IFoo:
        def fun1(self):
            pass
            raise Exception("----")
    
    class Bar(IFoo):
        def fun1(self):
            #方法名必须和父类中的方法名相同,不然没办法正常执行,会抛出异常
            print("子类中如果想要调用父类中的方法,子类中必须要有父类中的方法名")
        def fun2(self):
            print("test")
    
    obj = Bar()
    obj.fun2()
    View Code

    2.抽象方法抽象类

      抽象类,抽象方法是普通类和接口的综合,即可以继承也可以起到限制作用

      由于python 本身没有抽象类、接口的概念,所以要实现这种功能得abc.py 这个类库,具体实现方法如下 :

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    """
    抽象类,抽象方法
    抽象类,抽象方法是普通类和接口的综合,即可以继承也可以起到限制作用
    """
    
    import abc
    class Foo(metaclass=abc.ABCMeta):
        def fun1(self):
            print("fun1")
    
        def fun2(self):
            print("fun2")
    
        @abc.abstractclassmethod
        def fun3(self):
            pass
    
    
    class Bar(Foo):
        def fun3(self):
            print("子类必须有父类的抽象方法名,不然会抛出异常")
    
    
    obj = Bar()
    obj.fun1()
    obj.fun2()
    obj.fun3()
    View Code

    3. 组合

      python中“多用组合少用继承”,因为继承的偶合性太强,可以把基类,当做参数传入派生类中,用于解偶

    如;

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    #继承
    
    class Animals:
        def eat(self):
            print(self.Name + " eat")
        def drink(self):
            print(self.Name + " drink")
    
    class Person(Animals):
        def __init__(self, name):
            self.Name = name
    
        def think(self):
            print(self.Name + " think")
    obj = Person("user1")
    obj.drink()
    obj.eat()
    obj.think()
    继承
    class Animals:
        def __init__(self,name):
            self.Name = name
    
        def eat(self):
            print(self.Name + " eat")
    
        def drink(self):
            print(self.Name + " drink")
    
    class Person:
        def __init__(self, obj):
            self.obj = obj
    
        def eat(self):
            self.obj.eat()
    
        def think(self,name):
            print(name + " think")
    
    animals = Animals("animals")
    obj = Person(animals)
    obj.think("person")
    obj.eat()
    组合

    4.依赖注入

      刚接触理解的比较浅显

      像上一例中,如果有多层关系时,需要传入多个对象,为了解决这个问题就引入了依赖注入,如上例在Person类实例化时自动传入Animals对象

      那么,在引入依赖注入时先了解一下python类实例化过程中背后做了什么事情

    class Foo:
        def __init__(self):
            self.name = 111
        
        
        def fun(self)
            print(self.name)
            
    obj = Foo() #obj是Foo的实例化对象

    在python中一切皆对象,Foo是通过type类创建的

    例:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    class MyType(type):
    
        def __call__(cls, *args, **kwargs):
            obj = cls.__new__(cls, *args, **kwargs)
            obj.__init__(*args, **kwargs)
            return obj
    
    
    class Foo(metaclass=MyType):
    
        def __init__(self, name):
            self.name = name
    
        def f1(self):
            print(self.name)
     解释器解释:
        1.遇到 class Foo,执行type的__init__方法
        1.Type的init的方法里做什么么呢?不知道
            obj = Foo(123)
        3.执行Type的 __call__方法
            执行Foo类的 __new__方法
            执行Foo类的 __init__ 方法

    先来了解几个概念

    new 和 __init()和__metaclass__:

    • __new__函数是实例一个类所要调用的函数,每当我们调用obj = Foo()来实例一个类时,都是先调用__new__()

    • 然后再调用__init__()函数初始化实例. __init__()在__new__()执行后执行,

    • 类中还有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

    那么依赖注入的实现方法,自定义一个type方法,实例化类的时候指定由自定义的type方法创建,具体实现方法如下:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # 依赖注入应用
    #DI
    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 value(cls):
            return Mapper.__mapper_relation[cls]
    
    
    class MyType(type):
        def __call__(self, *args, **kwargs):
            obj = self.__new__(self, *args, **kwargs)
            arg_list = list(args)
            if Mapper.exist(self):
                value=Mapper.value(self)
                arg_list.append(value)
            obj.__init__(*arg_list, **kwargs)
            return obj
    
    
    #定义由谁来实例化
    class Foo(metaclass=MyType):
        def __init__(self,name):
            self.name = name
    
        def f1(self):
            print(self.name)
    
    class Bar(metaclass=MyType):
        def __init__(self,name):
            self.name = name
    
        def f1(self):
            print(self.name)
    
    Mapper.register(Foo,"test1")
    Mapper.register(Bar,"test12")
    f=Foo()
    print(f.name)
    依赖注入应用

    5.程序的设计原则

     1. 单一责任原则       

    一个对象只对一个元素负责

    优点;

      消除耦合,减小因需求变化引起代码僵化

      2.开放封闭原则

        对扩展开放,对修改关闭

        优点:

          按照OCP原则设计出来的系统,降低了程序各部分之间的耦合性,其适应性、灵活性、稳定性都比较好。当已有软件系统需要增加新的功能时,

          不需要对作为系统基础的抽象层进行修改,只需要在原有基础上附加新的模块就能实现所需要添加的功能。增加的新模块对原有的模块完全没有影响或影响很小,

          这样就无须为原有模块进行重新测试

        如何实现 ? 

          在面向对象设计中,不允许更必的是系统的抽象层,面允许扩展的是系统的实现层,所以解决问题的关键是在于抽象化。

          在面向对象编程中,通过抽象类及接口,规定具体类的特征作为抽象层,相对稳定,不需要做更改的从面可以满足“对修改关闭”的原则;而从抽象类导出的具体 类可以

          改变系统 的行为,从而满足“对扩展开放的原则"

      3.里氏替换原则  

        可以使用任何派生类替换基类
        优点:
          可以很容易的实现同一父类下各个子类的互换,而客户端可以毫不察觉
      4.接口分享原则
        对于接口进行分类避免一个接口的方法过多,避免”胖接口"
        优点:
          会使一个软件系统功能扩展时,修改的压力不会传到别的对象那里
        如何实现 ?
          得用委托分离接口
          利用多继承分离接口

      5.依赖倒置原则    

    隔离关系,使用接口或抽象类代指
    高层次的模块不应该依赖于低层次的模块,而是,都应该依赖于抽象
        优点:
          使用传统过程化程序设计所创建的依赖关系,策略依赖于细节,这是糟糕的,因为策略受到细节改变的影响。
          依赖倒置原则使细节和策略都依赖于抽象,抽象的稳定性决定了系统的稳定性
      6.依赖注入和控制反转原则
        
        使用钩子再原来执行流程中注入其他对象

    6. 目录规划

    注:

      Infrastructure 目录:公共组件目录

      Model:业务逻辑处理目录

      Repository: 数据仓库及数据处理目录

      Statics:静态文件目录如(css,js,images等)

      UIAdmin: UI层

      Views:模板文件目录

      Application.py : 服务启动文件

  • 相关阅读:
    设计模式
    idea多个项目
    多个tomcat配置
    mysql数据库默认时间字段格式
    读取文件
    上传图片
    数据库创建用户授权
    统计12个月份的数据
    行列转换
    分页
  • 原文地址:https://www.cnblogs.com/renfanzi/p/8335840.html
Copyright © 2011-2022 走看看