An in depth analysis of python3 relying on inversion principle of sample code

  • 2021-11-14 06:06:26
  • OfStack

Scene

For the parking information of the park, it is necessary to integrate the parking data provided by various companies and enter them into the big data platform of their own companies

The entry of data is nothing more than the addition, deletion and modification of data

The following 1 conventional writing (not consistent with dependence inversion) integrates parking data from Changan and Toyota


class Changan(object):
    def __init__(self):
        self.type = 'changan'

    def ca_add(self):
        print('%s  Add ' % self.type)

    def ca_del(self):
        print('%s  Delete ' % self.type)

    def ca_modify(self):
        print('%s  Modify ' % self.type)
        
    def ca_get(self):
        print('%s  Query ' % self.type)


class Toyota(object):
    def __init__(self):
        self.type = 'fengtian'

    def tyt_add(self):
        print('%s  Add ' % self.type)

    def tyt_del(self):
        print('%s  Delete ' % self.type)

    def tyt_modify(self):
        print('%s  Modify ' % self.type)

    def tyt_get(self):
        print('%s  Query ' % self.type)

class Data(object):

    def __init__(self, car):
        self.car = car

    def data_add(self):
        if self.car.type == 'changan':
            self.car.ca_add()
        else:
            self.car.tyt_add()

    def data_del(self):
        if self.car.type == 'changan':
            self.car.ca_del()
        else:
            self.car.tyt_del()

    def data_mofify(self):
        if self.car.type == 'changan':
            self.car.ca_modify()
        else:
            self.car.tyt_modify()

    def data_get(self):
        if self.car.type == 'changan':
            self.car.ca_get()
        else:
            self.car.tyt_get()

if __name__ == '__main__':
    ca = Changan()
    tyt = Toyota()
    autosystem = Data(ca)
    autosystem.data_add()
    autosystem.data_del()
    autosystem.data_modify()
    autosystem.data_get()
    autosystem.car = tyt
    print('*' * 50)
    autosystem.data_add()
    autosystem.data_del()
    autosystem.data_modify()
    autosystem.data_get()

The result of the run is as follows

changan Added
changan Delete
changan Modification
changan Query
**************************************************
fengtian Added
fengtian Delete
fengtian Modification
fengtian Query

It can be seen that the last Data class is a simple factory, and the data is added, deleted and checked in a process-oriented way. The upper Data class always depends on the lower Changan class and Toyota class. Assuming that the implementation of Changan class and Toyota class changes due to the change of requirements in the future, the Data class will also change, or a new manufacturer Suzuki Suzuki will come in the future, so many more if else will be written in Data. Such changes are fatal to programmers, and there are many places that need to be changed every time, so problems arise spontaneously.

How to solve it

Follow the principle of dependence inversion, according to

"Programs rely on abstract interfaces, not on concrete implementations. "

Through the commonality of changan and toyota, the methods of processing data are abstracted through interfaces


import abc

class DataProcessing(metaclass=abc.ABCMeta):
    """
     Abstract class 
     Abstract addition and modification 
    """
    @abc.abstractmethod
    def data_add(self, *args, **kwargs):
        pass

    @abc.abstractmethod
    def data_del(self, *args, **kwargs):
        pass

    @abc.abstractmethod
    def data_modify(self, *args, **kwargs):
        pass

    @abc.abstractmethod
    def data_get(self, *args, **kwargs):
        pass

class Changan(DataProcessing):
    def __init__(self):
        self.type = 'changan'

    def data_add(self):
        print('%s  Add ' % self.type)

    def data_del(self):
        print('%s  Delete ' % self.type)

    def data_modify(self):
        print('%s  Modify ' % self.type)
        
    def data_get(self):
        print('%s  Query ' % self.type)

class Toyota(DataProcessing):
    def __init__(self):
        self.type = 'fengtian'

    def data_add(self):
        print('%s  Add ' % self.type)

    def data_del(self):
        print('%s  Delete ' % self.type)

    def data_modify(self):
        print('%s  Modify ' % self.type)

    def data_get(self):
        print('%s  Query ' % self.type)

class Data(object):

    def __init__(self, car):
        self.car = car

    def data_add(self):
        self.car.data_add()

    def data_del(self):
        self.car.data_del()

    def data_modify(self):
        self.car.data_modify()

    def data_get(self):
        self.car.data_get()

if __name__ == '__main__':
    ca = Changan()
    tyt = Toyota()
    autosystem = Data(ca)
    autosystem.data_add()
    autosystem.data_del()
    autosystem.data_modify()
    autosystem.data_get()
    autosystem.car = tyt
    print('*' * 50)
    autosystem.data_add()
    autosystem.data_del()
    autosystem.data_modify()
    autosystem.data_get()

After running, the result is still

changan Added
changan Delete
changan Modification
changan query
**************************************************
fengtian Added
fengtian Delete
fengtian Modification
fengtian query

It can be seen from the above that the addition, deletion and modification have been abstracted into the methods in DataProcessing. In the future, no matter how the Changan classes and Toyota classes change, or a new Suzuki class needs to be added, the upper Data class does not need to be changed, and the client call does not need to be changed after if name = = 'main', and the code level is clearer, which is convenient for subsequent expansion.


Related articles: