[PYTHON] Design Pattern #Adapter

I practiced design patterns so that I could write code that was conscious of design. Other Design Patterns will be released frequently.

Preface

The primary goal is to understand when, what, and how to use design patterns. (I'm new to Java or a statically typed language, and I don't have a long history of python, so I think there are some things that aren't like Pythonista. If you have any suggestions, please teach me.)

This time, the pattern Adapter related to the structure.

What is Adapter

There are the following two types of Adapter patterns.

  1. Adapter pattern by class (using inheritance)
  2. Adapter pattern by instance (using delegation)

Create a conversion structure between the two classes and convert it so that it can be used for another purpose. Apdater is the role of the middle layer, and those who use it and those who use it do not need to know the contents. The point is the difference between returning as a class and returning as an instance.

Overview

Inheritance by class There is a sample program using the Apache pattern and a sample program by delegation. Both display the given string as (string) or \ * string \ *.

The Banner class has a method called show_with_paren that displays the character string in parentheses, and a method called show_with_paren that displays the character string with \ * marks before and after it. Suppose the Banner class is an existing one.

The Print interface declares a method print_weak to display a string weakly (in parentheses) and a method print_strong to display a string strongly.

The PrinterBanner class plays the role of an adapter. This class inherits from the provided Banner class and implements the required Printer interface. The PrinterBanner class now acts as an adapter.

Inheritance pattern class diagram

Adapter継承

Adapter inheritance pattern

banner.py


class Banner():

    def __init__(self, string):
        self.__string = string
        
    def show_with_paren(self):
        print('({0})').format(self.__string))
        
    def show_with_aster(self):
        print('({0})').format(self.__string))

printer.py


from abc import ABCMeta, abstractmethod

class Printer(metaclass=ABCMeta):
  
  @abstractmethod
  def print_weak(self):
      pass

  @abstractmethod      
  def print_strong(self):
      pass    

printer_banner.py


from banner import Banner


class PrinterBanner(Banner)

    def __init__(self, string):
        super().__init__(string)

    def print_weak(self):
        self.show_with_paren()
        
    def print_strong(self):
        self.show_with_aster()

The PrintBanner class acts as the Adapter.

Inherit the Banner class and inherit the show_with_paren and show_with_aster methods.

In addition, it implements the print_weak and print_strong methods with the required Printer interface.

main.py


from printer_banner import PrinterBanner

if __name__ == '__main__':
    pb = PrinterBanner('Bye')
    pb.print_weak() 
    pb.print_strong()

I am printing with print_weak () and print_strong () using the Printer interface. Since main does not know what kind of implementation the PrinterBanner class is, you can change the implementation of the PrinterBanner class without changing the main class.

Adapter delegation pattern

In the sample program by delegation, Main and Banner have the same inheritance pattern. The only difference is the PrintBanner class. In other words, we will use the Banner class to realize a class that has the same methods as the Printer class.

The PrinterBanner class holds an instance of the Banner class in the banner field. This instance is created by the constructor of the PrinterBanner class. Then, in the print_weak and print_strong methods, the show_with_paren and show_with_aster methods are called via the banner field.

If you use inheritance, you will call the show_with_paren and show_with_aster methods inherited from your superclass, but in the delegation pattern you will call them via fields.

When the print_weak method of the PrinterBanner class is called, it is left to the show_with_paren method of another instance (Banner instance) instead of handling it by itself. This is a delegation.

Class diagram of delegation pattern

Adapter 委譲

printer_banner.py


from printer import Printer
from banner import Banner


class PrinterBanner(Printer):

     def __init__(self, string):
         self.__banner = Banner(string)

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

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

This time, it inherits the Printer class and first calls an instance of the Banner class.

The print_weak and print_strong methods are implemented using the show_with_paren and show_with_aster methods for the called instance.

Only the wording is changed, but the output result is the same.

inheritance/main.py


(Bye)
*Bye*

delegation/main.py


(Hello)
*Hello*

Summary

The Adapter pattern covers the existing class and creates the required class. In other words, the interface part is inserted in between to make up for the gap between the two different parties.

Even if there is a bug, we know that there are no bugs in the existing class, so we should focus on the class that plays the role of Adapter, which makes checking the program very easy, and that the existing class If you only know the specifications, you can create a new class.

reference

Recommended Posts

Design Pattern #Adapter
Design Pattern #Builder
Design Pattern #Decorator
Design Pattern #Observer
Design Pattern #Facade
Design Pattern #Strategy
Design Pattern #Singleton
Design Pattern #Proxy
Learn the design pattern "Adapter" in Python
[Gang of Four] Design pattern learning --Adapter
Design Pattern #Factory Method
Design Pattern #Template Method
I wrote a design pattern in kotlin Adapter edition
Ore Ore Design Pattern: Glocal Variable
Python Design Pattern --Template method
[Gang of Four] Design pattern learning
GoF java design pattern rough summary
Learn the design pattern "Builder" in Python
[Gang of Four] Design Pattern Learning --Decorator
[Gang of Four] Design pattern learning --Visitor
Design pattern-Adapter
[Gang of Four] Design pattern learning --Mediator
Learn the design pattern "Flyweight" in Python
Learn the design pattern "Observer" in Python
Learn the design pattern "Memento" in Python
Learn the design pattern "Proxy" in Python
Learn the design pattern "Command" in Python
[Gang of Four] Design pattern learning --Iterator
GoF design pattern from the problem 2. Structure
Learn the design pattern "Visitor" in Python
Learn the design pattern "Bridge" in Python
Learn the design pattern "Mediator" in Python
Learn the design pattern "Decorator" in Python
Design pattern-Iterator
[Gang of Four] Design pattern learning --Facade
[Gang of Four] Design pattern learning --Composite
[Gang of Four] Design pattern learning --Prototype
GoF design pattern from the problem 1. Generation
Learn the design pattern "Iterator" in Python
[Gang of Four] Design pattern learning --Memento
[Gang of Four] Design pattern learning --State
[Gang of Four] Design pattern learning --Interpreter
[Gang of Four] Design pattern learning --Builder
Learn the design pattern "Strategy" in Python
[Gang of Four] Design pattern learning --Bridge
Learn the design pattern "Composite" in Python
Learn the design pattern "Singleton" with Python
Learn the design pattern "State" in Python
[Gang of Four] Design pattern learning --Proxy
[Gang of Four] Design pattern learning --Strategy
Learn the design pattern "Facade" with Python
[Gang of Four] Design pattern learning --Observer
[Gang of Four] Design pattern learning --Command
GoF design pattern from the problem 3. Behavior
[Gang of Four] Design pattern learning --Fly Weight
[Gang of Four] Design pattern learning --Abstract Factory
Learn the design pattern "Abstract Factory" in Python
Learn the design pattern "Template Method" in Python
[Gang of Four] Design pattern learning --Factory Method
Learn the design pattern "Factory Method" in Python
I wrote a design pattern in kotlin Prototype