Skip to content

面向对象设计SOLID原则

不积跬步无以至千里,不积小流无以成江海。

Author: 李东阳

1.开放封闭原则

一个软件实体,如类、模块、函数因该对扩张开发,对修改关闭。即软件实体应该尽量在不修改原来的代码的前提下进行扩展。

2.里氏替换原则

所有引用父类的地方必须能够透明地使用其子类的东西。

简单来说就是,将一个父类的对象传入一个函数。那么必须支持这个父类的子类对象也可以传入。

举个例子:

有一个函数是用来显示用户的信息,那么传入一个普通用户进去没有问题,就应该做到传入VIP用户也没有问题。(注:VIP用户是普通用户的子类)

class User:
    def show_info(self):
        pass


class VIPUser(User):
    def show_info(self):
        pass


def show_user(user):
    res = user.show_info()
    print(res)

# 想要实现里氏替换原则, 那么show_info的参数和返回值要相同

3.依赖倒置原则

高层模块不应该依赖底层模块, 二者应该依赖其抽象;抽象不应该依赖细节;细节应该依赖抽象。换而言之,要针对接口编程,而不是针对实现编程。总而言之,要遵循“国家规范”(前面讲过的哦)进行编程。

4.接口隔离原则

使用多个专门的接口,而不是使用单一的总接口,即高层代码不应该依赖那些它不需要的接口。

举个例子:

假设我们写一个Animal抽象类,这个类定义了walk、swim、fly方法。然后我们有Tiger、Frog、duck这三个类要去实现这个Animal抽象类。我们知道老虎会走,但是它不会游泳(我也不太清楚)和飞。青蛙会走(跳就算走吧)会游泳,但是它不会飞。鸭子就会走、游泳、飞了。这里面,那些动物不会的方法就是不需要的。所以很明显,我们这里的Animal抽象类就不合适了,所以我们要进行接口隔离,即把这个Animal抽象类分为几个抽象类: LandAnimal、WaterAnimal、SkyAnimal。老虎继承LandAnimal,鸭子继承LandAnimal和WaterAnimal,鸭子继承所有抽象类。

下面看看具体代码实现:

1.错误的方法

from abc import ABCMeta, abstractmethod


class Animal(mateclass=ABCMeta):
    @abstractmethod
    def walk(self):
        pass

    @abstractmethod
    def swim(self):
        pass

    @abstractmethod
    def fly(self):
        pass


class Tiger(Animal):
    def walk(self):
        print('老虎走路')

    # 我们应该知道抽象类的所有方法都应该实现,否则你懂的
    def swim(self):
        print('老虎游泳?')  # 应该不合理

    def fly(self):
        print('老虎飞?????')  # 显然不合理


class Forg(Animal):
    def walk(self):
        print('青蛙走路')

    def swim(self):
        print('青蛙游泳')

    def fly(self):
        print('青蛙飞?????')  # 显然不合理


class Duck(Animal):
    # 鸭子好牛逼啊
    def walk(self):
        print('鸭子走路')

    def swim(self):
        print('鸭子游泳')

    def fly(self):
        print('鸭子飞')

2.正确写法

from abc import ABCMeta, abstractmethod
# 拆分为多个抽象类
class LandAnimal(mateclass=ABCMeta):
    @abstractmethod
    def walk(self):
        pass


class WaterAnimal(mateclass=ABCMeta):
    @abstractmethod
    def swim(self):
        pass


class SkyAnimal(mateclass=ABCMeta):
    @abstractmethod
    def fly(self):
        pass


class Tiger(LandAnimal):
    def walk(self):
        print('老虎走路')


class Forg(LandAnimal, WaterAnimal):  # 分别继承抽象类
    def walk(self):
        print('青蛙走路')

    def swim(self):
        print('青蛙游泳')


class Duck(LandAnimal, WaterAnimal, SkyAnimal):  # 分别继承抽象类
    # 鸭子好牛逼啊
    def walk(self):
        print('鸭子走路')

    def swim(self):
        print('鸭子游泳')

    def fly(self):
        print('鸭子飞')

5.单一职责原则

不要存在多余一个导致类变更的原因。即一个类只负责一项职责。