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.