Adapteri kujundusmuster Pythonis

Sissejuhatus

. Adapteri disaini muster On populaarne Struktuurse disaini muster kasutatakse tarkvaratehnikas. Selles juhendis vaadeldakse, kuidas saaksime Pythonis adapteri kujundusmustrit rakendada.

Disainimustrid on mallitaolised lahendused – praktiliselt retseptid tarkvaraarenduse korduvate, levinud probleemide lahendamiseks. Adapteri muster põhineb tegeliku adapteri kontseptsioonil! Näiteks võib sülearvuti laadija otsas olla 3-kontaktiline pistik, kuid seinakontakt võib olla ainult 2-kontaktiline. 3-kontaktilise laadija ühendamiseks sellesse pistikupessa vajame adapterit, mis võtab vastu 3-kontaktilise pistiku ja kohaneb liidesesse 2-pin pistikupesa.

2-kontaktiline laadija ja 3-kontaktiline laadija on olemas sama põhifunktsioon (juhtida elektrit pistikupesast sülearvutisse), kuid on teistsugune vorm, ja seda saab lihtsalt kohandama teise sisse. Kui teil on sama põhifunktsiooniga, kuid erineva vormiga tarkvarakomponente, saate rakendada adapteri kujundusmustrit.

Adapteri muster järgib täpselt seda põhimõtet. See võimaldab kahel kokkusobimatul liidesel koos töötada ilma iga komponendi sisemisi muutmata. See saavutatakse ühe liidese kohandamisega teisega väliselt.

Enne adaptermustrite maailma sügavamale sukeldumist vaatame mõnda põhiterminoloogiat:

  • Kliendiliides: liides, mis määrab funktsioonid, mida klient peaks rakendama.
  • klient: klass, mis rakendab kliendiliidest.
  • Kohaneja/teenus: ühildumatu klass, mis peab tegema koostööd kliendiliidesega.
  • Adapter: klass, mis teeb võimalikuks koostöö teenuse ja kliendi vahel.

Erinevat tüüpi adapteri mustrid

Adapteri kujundusmustrit saab rakendada kahel erineval viisil:

Objekti adapter

Selle meetodi abil rakendab adapterklass meetodeid kliendiliidesest. Seega on kliendiobjekt ja adapterobjekt omavahel ühilduvad. Teenusobjekt moodustab a has-a seos adapterobjektiga, st teenindusobjekt kuulub adapterobjekti.

Teame, et teenindusklass ei ühildu kliendiga. Adapteriklass ümbritseb teenindusobjekti, instantseerides end selle objektiga. Nüüd pääseb teenindusobjektile juurde adapterobjekti kaudu, võimaldades kliendil sellega suhelda.

Objektiadapterit saame rakendada kõigis kaasaegsetes programmeerimiskeeltes.

Klassi adapter

Selle meetodi korral on adapteril is-a suhe teenindusklassiga. Selle stsenaariumi korral rakendab adapter kliendi nõutud meetodeid, kuid pärib mitmelt kohandajalt, andes talle võimaluse nende ühildumatutele funktsioonidele otse helistada. Selle variatsiooni suurim puudus on see, et saame seda kasutada ainult nendes programmeerimiskeeltes, mis toetavad mitut klasside pärimist.

Adapteri disaini mustri rakendamine Pythonis

Allolevas jaotises rakendame Pythonis Adapteri kujundusmustri, kasutades selleks konkreetselt objekti adapteri variatsioon. Sektsioon on jagatud kaheks osaks. Esiteks loome keskkonna, kus Adapteri mustrit kasutada. Oluline on selgelt näha, kuidas see muster võib mõningaid tarkvaraprobleeme lahendada. Teises jaotises kasutatakse probleemi lahendamiseks adapterit.

Klasside kokkusobimatuse probleem

Vaatame ühilduvusprobleemi, kui klient ja teenuseklass rakendavad erinevaid funktsioone. Looge järgmiste meetoditega kliendiklass ja salvestage see kausta nimega car.py:

import random

class Car:
    def __init__(self):
        self.generator = random.Random()

    def accelerate(self):
        random_num = self.generator.randint(50, 100)
        speed = random_num
        print(f"The speed of the car is {speed} mph")

    def apply_brakes(self):
        random_num = self.generator.randint(20, 40)
        speed = random_num
        print(f"The speed of the car is {speed} mph after applying the brakes")

    def assign_driver(self, driver_name):
        print(f"{driver_name} is driving the car")

Siin oleme loonud a Car klassi kolme meetodiga accelerate(), apply_brakes() ja assign_driver(). Importisime random moodulit ja kasutas seda numbrite genereerimiseks, mis määravad pärast kiirendamist ja pidurite rakendamist auto kiirust. The assign_driver() meetod kuvab autojuhi nime.

Järgmiseks peame looma teenuse- või kohandamisklassi, mis soovib kliendiklassiga koostööd teha Car. Looge selline mootorrattaklass ja salvestage see oma kausta nimega motorcycle.py:

import random

class Motorcycle:
    def __init__(self):
        self.generator = random.Random()

    def rev_throttle(self):
        random_num = self.generator.randint(50, 100)
        speed = random_num
        print(f"The speed of the motorcycle is {speed} mph")

    def pull_brake_lever(self):
        random_num = self.generator.randint(20, 40)
        speed = random_num
        print(
            f"The speed of the motorcycle is {speed} mph after applying the brakes")

    def assign_rider(self, rider_name):
        print(f"{rider_name} is riding the motorcycle")  

Teenindusklass, Motorcycle on loodud ülalpool kolme meetodiga rev_throttle(), pull_brake_lever()ja assign_rider(). Märka erinevust teenuse ja kliendiklassi meetodite vahel, hoolimata nende sarnasest funktsionaalsusest. The accelerator() meetod suurendab auto kiirust samal ajal rev_throttle() meetod suurendab mootorratta kiirust. Samamoodi apply_brakes() ja pull_brake_lever() rakendab vastavates sõidukites pidureid. Lõpuks, assign_driver() ja assign_rider() meetodid määravad sõiduki operaatori.

Järgmisena loome nendele erinevatele meetoditele juurdepääsu saamiseks klass. Esiteks lisage an __init.py__ samas kaustas, mille lõite car.py ja motorcycle.py:

touch __init__.py

Nüüd lisage järgmine kood uude faili drive.py:

from car import Car
from motorcycle import Motorcycle
import traceback

if __name__ == '__main__':
    car = Car()
    bike = Motorcycle()

    print("The Motorcyclen")
    bike.assign_rider("Subodh")
    bike.rev_throttle()
    bike.pull_brake_lever()
    print("n")

    print("The Carn")
    car.assign_driver("Sushant")
    car.accelerate()
    car.apply_brakes()
    print("n")

    print("Attempting to call client methods with the service objectn")

    try:
        bike.assign_driver("Robert")
        bike.accelerate()
        bike.apply_brakes()
    except AttributeError:
        print("Oops! bike object cannot access car methods")
        traceback.print_exc()

See skript, mis loob meie kliendi- ja teenuseobjektid. Esmalt impordime Car ja Motorcycle klassidesse ja luua nendega objekte. Seejärel kutsume välja meetodid bike objekt (Motorcycle klass). Pärast seda kasutame meetodeid car objekt (Car klass). Täitmisel töötab kogu seni mainitud kood.

Siiski tehakse erand, kui proovime kasutada meetodi meetodeid Car klass koos bike objektiks. Kui käivitame selle skripti:

The Motorcycle

Subodh is riding the motorcycle
The speed of the motorcycle is 91 mph
The speed of the motorcycle is 37 mph after applying the brakes


The Car

Sushant is driving the car
The speed of the car is 59 mph
The speed of the car is 33 mph after applying the brakes


Attempting to call client methods with the service object

Oops! bike object cannot access car methods
Traceback (most recent call last):
  File "drive.py", line 24, in 
    bike.assign_driver("Robert")
AttributeError: 'Motorcycle' object has no attribute 'assign_driver'

Sel juhul saame muuta Motorcycle klass või drive.py skript, et kasutada õigeid meetodeid. Kuid paljudel juhtudel ei pruugi meil olla juurdepääsu kliendi või teenuseklassi lähtekoodile. Lisaks on see lihtne näide. Suuremate klientide ja teenuste puhul ei pruugi olla võimalik kumbagi neist ümber kujundada, kui rikume ühilduvust teiste süsteemidega.

Selle asemel saame kasutada adapterit, et ületada meie kliendikoodi ja teenindusobjekti vaheline ühilduvus.

Adapterite kasutamine ühildumatuse probleemi lahendamiseks

Uues failis motorcycle_adapter.py, lisage järgmine klass:

class MotorcycleAdapter:

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

    def accelerate(self):
        self.motorcycle.rev_throttle()

    def apply_brakes(self):
        self.motorcycle.pull_brake_lever()

    def assign_driver(self, name):
        self.motorcycle.assign_rider(name)

Oleme loonud a MotorcycleAdapter klass, mis instantseerib end teenuseobjektiga (motorcycle). Adapter rakendab kliendi meetodeid, mis on accelerate(), apply_brakes() ja assign_driver(). Keha sees accelerate() meetodit, oleme kasutanud motorcycle teenuseobjekti eksemplar, millele helistada rev_throttle() teenindusmeetod. Samuti kasutavad teised meetodid vastavaid meetodeid Motorcycle klass.

Nüüd värskendame drive.py et saaksime selles adapterit kasutada try/except plokk:

from car import Car
from motorcycle import Motorcycle
from motorcycle_adapter import MotorcycleAdapter 
import traceback

if __name__ == '__main__':
    car = Car()
    bike = Motorcycle()
    bike_adapter = MotorcycleAdapter(bike) 

    ...

    try:
        print("Attempting to call client methods with the service object using an adaptern")
        bike_adapter.assign_driver("Robert")
        bike_adapter.accelerate()
        bike_adapter.apply_brakes()
    except AttributeError:
        print("Oops! bike object cannot access car methods")
        traceback.print_exc()

Siinbike_adapter on objekt MotorcycleAdapter klass. Varustasime bike vastu MotorcycleAdapter klassi konstruktor. Selle skripti käivitamine annab meile järgmise väljundi:

Tutvuge meie praktilise ja praktilise Giti õppimise juhendiga, mis sisaldab parimaid tavasid, tööstusharus aktsepteeritud standardeid ja kaasas olevat petulehte. Lõpetage Giti käskude guugeldamine ja tegelikult õppima seda!

The Motorcycle

Subodh is riding the motorcycle
The speed of the motorcycle is 88 mph
The speed of the motorcycle is 35 mph after applying the brakes


The Car

Sushant is driving the car
The speed of the car is 91 mph
The speed of the car is 24 mph after applying the brakes


Attempting to call client methods with the service object

Attempting to call client methods with the service object using an adapter

Robert is riding the motorcyle
The speed of the motorcycle is 67 mph
The speed of the motorcycle is 25 mph after applying the brakes

Ilma, et peaksite aluspinda kohandama Motorcycle klassi, saame selle tööle nagu a Car kasutades adapterit!

Adapteri disainimustri plussid ja miinused

Adapteri mustrite eelised on järgmised:

  • Saame saavutada madala sidestuse adapteriklassi ja kliendiklassi vahel.
  • Adapteriklassi saame uuesti kasutada, et lisada rakendusse palju teenuseklasse.
  • Programmi paindlikkust saame suurendada, kui võtame kasutusele mitu adapterit ilma kliendikoodi segamata

Adapteri mustri puudused on järgmised:

  • Programmi keerukus suureneb adapteriklassi ja teenindusklassi lisamisega.
  • Programmi üldkulud suurenevad, kuna päringud edastatakse ühest klassist teise.
  • Adapteri muster (klassi adapter) kasutab mitut pärandit, mida kõik programmeerimiskeeled ei pruugi toetada.

Järeldus

Sellest artiklist saime teada adapteri kujundusmustri, selle tüüpide ja nendega lahendatavate probleemide kohta. Rakendasime Pythonis adapteri mustri, et saaksime suhelda a Motorcycle objekt, nagu a Car objekti, kasutades adapterit, nii et iga klassi liides ei muutuks.

Ajatempel:

Veel alates Stackabus