Design Pattern Adapter Pattern (Adapter Pattern)

Preface

In daily life, we often encounter situations like this: we encounter a problem that needs to be solved. The existing tools in our hands cannot solve the problem directly. We need to make adjustments. For example, the water pipe needs to be extended to meet our distance requirements. However, the existing water pipes have different diameters. At this time, an adapter is needed to splice two water pipes of different diameters. Problems like this abound. For example, the data cables connected to the computer screen come in various formats, such as DVI, VGA, HDMI, etc. It is also often encountered that an adapter must be used to connect one end to a VGA interface and the other end to an HDMI interface. Another example is household electricity. The voltage is the voltage required by the electrical appliance and is not consistent, so it also needs to be converted at this time.

Then in the programming world, we will naturally encounter similar problems. Existing programs can solve most of the demand problems, but they cannot be used directly! Therefore, an adapter is needed to connect the existing program with the required program . We call this mode the adapter mode, also called the Adapter mode.

Mode introduction

class design

analog reality kind
The actual situation Large diameter water pipe Banner class
adapter Adapter PrintBanner class
demand situation small diameter water pipe Print interface

UML-like diagram

UML class diagram

Code

In this example, a simple class for printing strings is used. We currently have an existing class Banner, whose function is to add brackets or * signs to the given string and print it to the console. Suppose we now have a new requirement, which requires weak display and strong display of the given string, corresponding to adding brackets and adding * respectively. And we cannot use Banner class methods directly, because these two methods belong to the protection level and are not open to the outside world. So we need to write a class, inherit from Banner, and open this method.

Banner class

"""
@Time: 2023/3/18 22:54
@Auth: CivilDog
@File: Banner.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""


class Banner:
    """
    打印字符串的类,类比现有程序
    """
    def __init__(self, str_to_print: str):
        self.__str_to_print = str_to_print

    def _show_with_paren(self):
        print("("+self.__str_to_print+")")

    def _show_with_aster(self):
        print("*"+self.__str_to_print+"*")

PrintInterface class

"""
@Time: 2023/3/18 22:57
@Auth: CivilDog
@File: PrintInterface.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""
import abc
from abc import ABCMeta


class PrintInterface(metaclass=ABCMeta):
	"""
	打印类的接口类,抽象出需求所需要的方法,并由实际使用类所继承和实现
	"""
    @abc.abstractmethod
    def print_weak(self):
        pass

    @abc.abstractmethod
    def print_strong(self):
        pass

PrintBanner class

"""
@Time: 2023/3/18 22:58
@Auth: CivilDog
@File: PrintBanner.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""
from DesignMode.AdapterMode.PrintInterface import PrintInterface
from DesignMode.AdapterMode.Banner import Banner


class PrintBanner(PrintInterface, Banner):
	"""
	多重继承PrintInterface和Banner,实现父类定义的抽象方法,和开放protected级别的方法
	"""
    def __init__(self, str_to_print: str):
        super(PrintBanner, self).__init__(str_to_print)

    def print_weak(self):
        self._show_with_paren()

    def print_strong(self):
        self._show_with_aster()

AdapterClient class

"""
@Auth: CivilDog
@File: AdapterClient.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""
from DesignMode.AdapterMode.PrintBanner import PrintBanner


class AdapterClient:
    """
    Adapter模式的测试入口
    """

    @staticmethod
    def run(*args, **kwargs):
        str_to_print = "Hello World!"
        p_b = PrintBanner(str_to_print)
        p_b.print_weak()
        p_b.print_strong()


if __name__ == '__main__':
    AdapterClient.run()

Output results

(Hello World!)
*Hello World!*

Process finished with exit code 0

Use delegation to avoid multiple inheritance

Because multiple inheritance may introduce new problems, and they are often difficult to troubleshoot. So sometimes projects require you to avoid multiple inheritance as much as possible!
At this time, you can switch to the delegation method, that is, delegate the work of the PrintBanner class to other classes, that is, the Banner class. This method can also open the interface we need without exposing the Banner class itself.

The delegation method is also a common programming method in program development.

Banner class

"""
@Time: 2023/3/18 22:54
@Auth: CivilDog
@File: Banner.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""


class Banner:
    """
    打印字符串的类,类比现有程序
    """
    def __init__(self, str_to_print: str):
        self.__str_to_print = str_to_print

    def show_with_paren(self):
        print("("+self.__str_to_print+")")

    def show_with_aster(self):
        print("*"+self.__str_to_print+"*")

PrintBanner class

class PrintBanner(PrintInterface):

    def __init__(self, str_to_print: str):
        super(PrintBanner, self).__init__()
        self.__banner = Banner(str_to_print)

    def print_weak(self):
        self.__banner.show_with_paren()

    def print_strong(self):
        self.__banner.show_with_aster()

Summarize

Why use adapter pattern

The above is a simple example. In fact, if you want to realize this requirement, you can directly modify the Banner class and expose the method. Why bother to create two extra classes?

Avoid affecting the original code and reduce costs

The example is to let everyone understand how to use the adapter pattern. The actual development situation and development requirements are much more complicated than this. Our existing programs are generally put online after rigorous testing. If changes are made directly based on the source code because of new requirements, it will need to be re-tested, which is more expensive and prone to problems with a larger impact.

Using the adapter mode can avoid this situation. The original code has been tested and is relatively stable, and it all runs online. Through adaptation, existing code is used in new projects and new requirements. Even if a problem occurs, it is easy to determine that it is a problem with the adapted code.

Only interfaces are needed to implement new classes

The python language is open source, but many compiled languages ​​are often not open source, but provide some APIs for external calls. At this time, in the project, in order to avoid exposing third-party things, we usually encapsulate a class by ourselves. It's adapter mode.

It often appears in version upgrades

The software life cycle is always accompanied by upgrades. In rare cases, it is possible to completely abandon the old version, so the compatibility issue between the old and new versions is often a headache. Adapter mode can help us deal with this situation easily!

When can't you use adapter mode?

When there is a complete mismatch between the existing program and the requirements, it will naturally not be used and you will have to implement the new class yourself.

"Illustrative Design Pattern" Hiroshi Yuki

Guess you like

Origin blog.csdn.net/weixin_43500200/article/details/129644393