项目设计原则

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

1. 接口

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

  接口做用:对派生类起到限制的做用编程

例:app

#!/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.抽象方法抽象类

  抽象类,抽象方法是普通类和接口的综合,便可以继承也能够起到限制做用ide

  因为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中“多用组合少用继承”,由于继承的偶合性太强,能够把基类,当作参数传入派生类中,用于解偶测试

如;spa

#!/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对象3d

  那么,在引入依赖注入时先了解一下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 : 服务启动文件

相关文章
相关标签/搜索