项目设计原则
开始之前需要引入一些项目设计知识,如接口,抽象方法抽象类,组合,程序设计原则等,个人理解项目的合理设计可增加其灵活性,降低数据之间的耦合性,提高稳定性,下面介绍一些预备知识
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()
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()
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.程序的设计原则
一个对象只对一个元素负责
优点;
消除耦合,减小因需求变化引起代码僵化
2.开放封闭原则
对扩展开放,对修改关闭
优点:
按照OCP原则设计出来的系统,降低了程序各部分之间的耦合性,其适应性、灵活性、稳定性都比较好。当已有软件系统需要增加新的功能时,
不需要对作为系统基础的抽象层进行修改,只需要在原有基础上附加新的模块就能实现所需要添加的功能。增加的新模块对原有的模块完全没有影响或影响很小,
这样就无须为原有模块进行重新测试
如何实现 ?
在面向对象设计中,不允许更必的是系统的抽象层,面允许扩展的是系统的实现层,所以解决问题的关键是在于抽象化。
在面向对象编程中,通过抽象类及接口,规定具体类的特征作为抽象层,相对稳定,不需要做更改的从面可以满足“对修改关闭”的原则;而从抽象类导出的具体 类可以
改变系统 的行为,从而满足“对扩展开放的原则"
3.里氏替换原则
5.依赖倒置原则
6. 目录规划
注:
Infrastructure 目录:公共组件目录
Model:业务逻辑处理目录
Repository: 数据仓库及数据处理目录
Statics:静态文件目录如(css,js,images等)
UIAdmin: UI层
Views:模板文件目录
Application.py : 服务启动文件
出处:http://www.cnblogs.com/renfanzi/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。