項目設計原則

開始以前須要引入一些項目設計知識,如接口,抽象方法抽象類,組合,程序設計原則等,我的理解項目的合理設計可增長其靈活性,下降數據之間的耦合性,提升穩定性,下面介紹一些預備知識 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 : 服務啓動文件

相關文章
相關標籤/搜索