单一职责原则(SRP:Single responsibility principle),一个类或者模块应该有且只有一个改变的原因,例如,搓衣板,既可以用来跪,也可以用来洗衣服。而在单一职责原理下,搓衣板的两个功能就是引起这个类变化的两个原因,就应该写成两个类
# -*- coding: utf-8 -*-
"""
单一职责原则
"""
class Person(object):
""" 人类 """
def duty(self, one):
""" Coder 的职责是写代码 ,农民就负责斗地主,其余的学习 """
return one is "Coder" and "Coding" or one is "Farmer" and "Chinese poker" or "Studying"
if __name__ == '__main__':
p = Person()
print(p.duty("Coder"))
- 此时如果细分责任到每一个人,岂不是一堆的判断,肯定不科学,所以尽量让一个类或者一个模块做一件事
# -*- coding: utf-8 -*-
"""
单一职责原则
"""
class Person(object):
""" 人类 """
def duty(self, one):
""" Coder 的职责是写代码 ,农民就负责斗地主,其余的学习 """
return one is "Coder" and "Coding" or one is "Farmer" and "Chinese poker" or "Studying"
class Coder(Person):
""" 农民 """
def duty(self):
""" Coder 的职责是写代码 """
return "Coding"
class Farmer(Person):
""" 程序员 """
def duty(self):
""" 农民就负责斗地主 """
return "Chinese poker"
if __name__ == '__main__':
c = Coder()
print(c.duty())
f = Farmer()
print(f.duty())
里氏替换原则( LSP:Liskov Substitution Principle):任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为
子类必须完全实现父类的抽象方法,但不能覆盖父类的非抽象方法
子类可以实现自己特有的方法
当子类覆盖或实现父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。
当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
子类的实例可以替代任何父类的实例,但反之不成立
# -*- coding: utf-8 -*-
import abc
import time
"""
里氏替换原则
"""
HOUR = 3600
class Person(object):
""" 人类 """
@abc.abstractmethod
def duty(self):
""" 职责 """
pass
class Coder(Person):
""" 程序员 """
def duty(self):
""" Coder 的职责是写代码 """
return "Coding"
def sleep(self):
""" 有时睡5小时 """
time.sleep(5*HOUR)
class Farmer(Person):
""" 程序员 """
def duty(self):
""" 农民就负责斗地主 """
return "Chinese poker"
def sleep(self):
""" 农民可以睡八小时 """
time.sleep(8*HOUR)
依赖倒置原则(Dependence Inversion Principle):高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象
# -*- coding: utf-8 -*-
import abc
import time
"""
里氏替换原则
"""
HOUR = 3600
class Person(object):
""" 人类 """
@abc.abstractmethod
def duty(self):
""" 职责 """
pass
class Coder(Person):
""" 程序员 """
def duty(self):
""" Coder 的职责是写代码 """
return "Coding"
def sleep(self):
""" 睡5小时 """
time.sleep(5*HOUR)
接口隔离原则(Interface Segregation Principle) 这个原则的意思是:每个接口中不存在子类用不到却必须实现的方法,如果不然就要将接口拆分,使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个接口)要好
# -*- coding: utf-8 -*-
"""
接口隔离原则
"""
import abc
import time
import types
HOUR = 3600
class Person(object):
""" 人类 """
@abc.abstractmethod
def duty(self):
""" 职责 """
pass
class Coder(Person):
""" 程序员 """
def duty(self):
""" Coder 的职责是写代码 """
return "Coding"
def sleep(self):
""" 有时睡5小时 """
time.sleep(5*HOUR)
# 方法一
# def programme(self, language='Php'):
# """ 实例动态方法 """
# return language
# 方法二
# @classmethod
# def programme(cls, language='Php'):
# """ 类动态方法 """
# return language
# 方法三
@staticmethod
def programme(language='Php'):
""" 静态方法 """
return language
if __name__ == '__main__':
# 方法一:给实例绑定方法
# p = Coder()
# p.programme = types.MethodType(programme, p)
# print(p.programme('Python'))
# 方法二:
# p = Coder()
# Coder.programme = programme
# print(Coder.programme('Java'))
# print(p.duty())
# 方法三:静态方法
p = Coder()
Coder.programme = programme
print(Coder.programme('Java'))
print(p.programme('Golang'))
print(p.duty())
迪米特原则: 一个对象应该对其他对象保持最少的了解。
问题由来:类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大。
解决方案:尽量降低类与类之间的耦合。
软件编程的总的原则:低耦合,高内聚。无论是面向过程编程还是面向对象编程,只有使各个模块之间的耦合尽量的低,才能提高代码的复用率。低耦合的优点不言而喻,要做到低耦合,正是迪米特法则要去完成的。
迪米特法则又叫最少知道原则,最早是在1987年由美国Northeastern University的Ian Holland提出。通俗的来讲,就是一个类对自己依赖的类知道的越少越好。也就是说,对于被依赖的类来说,无论逻辑多么复杂,都尽量地的将逻辑封装在类的内部,对外除了提供的公共方法,不对外泄漏任何信息。迪米特法则还有一个更简单的定义:只与直接的朋友通信。首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。
开闭原则:一个软件实体如类、模块和函数应该对扩展开放,对修改关闭
- 不要改你以前写的代码,你应该加一些代码去扩展原来的功能,来实现新的需求。好处很好理解,改原来的代码很容易影响原来的功能,特别是接手别人的代码,不理解原先业务场景的情况下。