An Interest In:
Web News this Week
- April 23, 2024
- April 22, 2024
- April 21, 2024
- April 20, 2024
- April 19, 2024
- April 18, 2024
- April 17, 2024
Design Pattern in Python (4): Adapter Pattern
Today I would like to do some coding work on Adapter Pattern in Python.
Adapter is one of the Structural Patterns.
It works as a bridge between two incompatible interfaces. This pattern involves a single class which is responsible to join functionalities of independent or incompatible interfaces.
I found easily one real life example of "adapter" in my room. I have a laptop of brand Redmi which has a chinese type power plug. I am living in France and thus I have only European type socket at home. It's not possible to insert directly my laptop's plug into a french socket.
To solve the issue, I am using an adapter to charge my laptop. This small gadget is really very practical for me.
Thus I would like to code this example in Python today. Let's go!
1st simulation: Incompatible issue
Socket simulation
Firstly I define several classes for sockets including PowerSocket
base class and its concrete classes.
class PowerSocket(): """ PowerSocket base class """ def __init__ (self, holeNum, Shape, Volt): self.__num_holes = holeNum self.__hole_shape = Shape self.__volt = Volt def getHoleNum (self): return self.__num_holes def getHoleShape (self): return self.__hole_shape def getVolt (self): return self.__volt ### some concrete PowerSocket classesclass chineseSocket(PowerSocket): def __init__ (self): super().__init__( 3, "FLAT", 220) class europeanSocket(PowerSocket): def __init__ (self): super().__init__( 2, "ROUND", 220) class taiwaneseSocket(PowerSocket): def __init__ (self): super().__init__( 2, "FLAT", 110)
Laptop simulation
Now a class of my Laptop with its plug class. Method charge()
of RedmiLaptop
class shall check if socket is compatible with its power plug.
class chinise3pinPlug(): def __init__ (self): self.pins = 3 self.volt = 220 self.pinshape = "FLAT" class RedmiLaptop(): def __init__ (self): self.plug = chinise3pinPlug() def charge(self, socket, powerInWatt): res = False if (isinstance(socket, PowerSocket)): res = (self.plug.pins == socket.getHoleNum() ) and \ (self.plug.pinshape == socket.getHoleShape() ) and \ (self.plug.volt == socket.getVolt() ) else: print ("Socket is not instance of PowerSocket") if res: current = round(powerInWatt / self.plug.volt, 2) print("Start charging... Power: {} watt; Socket current: {} am ...".format(str(powerInWatt), str(current))) else: print("Socket and plug not compatible, impossible to charge.") return res
Charging simulation
Now launch the simulation. I move to 3 different areas in this simulation and see if I can charge my laptop there.
if __name__ == "__main__": laptop = RedmiLaptop() # instance of my Redmi Laptop # I am in china mainland chSocket = chineseSocket() laptop.charge(socket=chSocket, powerInWatt=235) # I am in France euSocket = europeanSocket() laptop.charge(socket=euSocket, powerInWatt=235) # I am in Taipei twSocket = taiwaneseSocket() laptop.charge(socket=twSocket, powerInWatt=235)
2nd Simulation: adapter usage
Adapter simulation
Now I introduce a SocketAdapter
base class as adapter interface for socket conversion. I define a AnyToChineseAdapter
concrete class to simulate a multi-usage converter for chinese-type plug of my laptop. AnyToChineseAdapter
has a output socket of chinese type. It implements a core method convert()
which is responsible to convert different socket interfaces to chinese type, namely it bridges various socket types to chinese-type plugs.
class SocketAdapter(): """ SocketAdapter base class """ def __init__ (self ): pass def convert(self ): pass def getSocket (self): passclass AnyToChineseAdapter(SocketAdapter): """ A concrete SocketAdapter class that can convert any socket to chinese socket """ def __init__ (self): super().__init__() self.__outSocket = chineseSocket() self.__voltRatio = 1 self.__plug = "" def convert(self, fromSocket): res = True if isinstance (fromSocket, chineseSocket): self.__voltRatio = 1 self.__plug = "Chinese format Plug" print("Chinese to Chinese using {}".format(self.__plug)) elif isinstance (fromSocket, europeanSocket): self.__voltRatio = 1 self.__plug = "European format Plug" print("European to Chinese using {}".format(self.__plug)) elif isinstance (fromSocket, taiwaneseSocket): self.__voltRatio = 2 self.__plug = "Taiwanese format Plug" print("Taiwanese to Chinese using {}".format(self.__plug)) # elif isinstance (fromSocket, someSocket): # do converting stuff... else: print("Unknown socket, cannot choose plug format and volt convertion ratio") res = False return res def getSocket(self): return self.__outSocket def getVoltRatio(self): return self.__voltRatio
Socket simulation
I define PowerSocket
base class and its concrete classes. This part is almost the same as in the first simulation. I define one extra class martianSocket
for simulating socket on Mars.
class PowerSocket(): """ PowerSocket base class """ def __init__ (self, holeNum, Shape, Volt): self.__num_holes = holeNum self.__hole_shape = Shape self.__volt = Volt def getHoleNum (self): return self.__num_holes def getHoleShape (self): return self.__hole_shape def getVolt (self): return self.__volt ### some concrete PowerSocket classesclass chineseSocket(PowerSocket): def __init__ (self): super().__init__( 3, "FLAT", 220)class europeanSocket(PowerSocket): def __init__ (self): super().__init__( 2, "ROUND", 220) class taiwaneseSocket(PowerSocket): def __init__ (self): super().__init__( 2, "FLAT", 110) class martianSocket(PowerSocket): def __init__ (self): super().__init__( 2, "FLAT", 300)
Laptop simulation
A modification in Laptop class regarding the 1st simulation is that now it has a private member __adapter
which is an instance of AnyToChineseAdapter
. A new method addAdapter
should be called to attach a SocketAdapter
instance.
class chinise3pinPlug(): def __init__ (self): self.pins = 3 self.volt = 220 self.pinshape = "FLAT" class RedmiLaptop(): def __init__ (self): self.plug = chinise3pinPlug() self.__adapter = None def addAdapter(self, adpt): self.__adapter = adpt def charge(self, inSocket, powerInWatt): res = False if (isinstance(inSocket, PowerSocket)) : if self.__adapter.convert(inSocket): socket = self.__adapter.getSocket() res = (self.plug.pins == socket.getHoleNum() ) and \ (self.plug.pinshape == socket.getHoleShape() ) and \ (self.plug.volt == socket.getVolt() ) else: res = False else: print ("Socket is not instance of PowerSocket") if res: current = round(powerInWatt / self.plug.volt, 2) * self.__adapter.getVoltRatio() print("Start charging... Power: {} watt; Socket current: {} am ...".format(str(powerInWatt), str(current))) else: print("Socket and plug not compatible, impossible to charge.") return res
Charging simulation
Now launch the 2nd simulation. I move firstly to 3 different areas on earth and finally go on Mars in this simulation and see if I can charge my laptop there.
if __name__ == "__main__": redmiAd = AnyToChineseAdapter() laptop = RedmiLaptop() laptop.addAdapter(redmiAd) # I am in china mainland chSocket = chineseSocket() laptop.charge(chSocket, powerInWatt=235) # I am in France euSocket = europeanSocket() laptop.charge(euSocket, powerInWatt=235) # I am in Taipei twSocket = taiwaneseSocket() laptop.charge(twSocket, powerInWatt=235) # I am on Mars msSocket = martianSocket() laptop.charge(msSocket, powerInWatt=235)
See, I can charge my laptop with chinese, european and taiwanese sockets. However, I cannot charge it on Mars, since the adapter does not (yet) have conversion method for martian socket type.
Original Link: https://dev.to/jemaloq/design-pattern-in-python-4-adapter-pattern-g74
Dev To
An online community for sharing and discovering great ideas, having debates, and making friendsMore About this Source Visit Dev To