Predstavitev
O Vzorec zasnove adapterja je priljubljena Strukturni vzorec oblikovanja uporablja v programskem inženiringu. Ta vodnik obravnava, kako lahko implementiramo vzorec načrtovanja adapterja v Python.
Oblike oblikovanja so predloge podobne rešitve – praktično recepti za reševanje ponavljajočih se pogostih težav pri razvoju programske opreme. Vzorec adapterja temelji na konceptu adapterja iz resničnega sveta! Na primer, polnilnik prenosnega računalnika ima lahko 3-polni vtič na koncu, stenska vtičnica pa je lahko samo 2-polna vtičnica. Za priključitev 3-polnega polnilnika v to vtičnico bi potrebovali adapter, ki sprejme 3-polni vtič in prilagaja vmesnik v 2-pin vtičnica.
2-polni polnilec in 3-polni polnilec imata enako osnovno funkcijo (prevajajo elektriko iz vtičnice v prenosnik), vendar imajo drugačna oblika, in lahko enostavno prilagodijo v drugo. Kadarkoli imate komponente programske opreme z isto osnovno funkcijo, vendar različnih oblik, lahko uporabite vzorec načrtovanja adapterja.
Vzorec adapterja sledi točno temu načelu. Omogoča, da dva nezdružljiva vmesnika delujeta skupaj, ne da bi spremenili notranjost vsake komponente. To se doseže s prilagajanjem enega vmesnika drugemu navzven.
Oglejmo si nekaj osnovne terminologije, preden se poglobimo v svet vzorcev adapterjev:
- Odjemalski vmesnik: Vmesnik, ki določa funkcije, ki naj bi jih izvajal odjemalec.
- Pomoč: razred, ki implementira vmesnik odjemalca.
- Adaptator/Servis: Nezdružljiv razred, ki mora sodelovati z odjemalskim vmesnikom.
- Adapter: razred, ki omogoča sodelovanje med storitvijo in odjemalcem.
Različne vrste vzorcev adapterjev
Vzorec zasnove adapterja je mogoče implementirati na dva različna načina:
Predmetni adapter
S to metodo razred adapterja izvaja metode iz odjemalskega vmesnika. Tako sta objekt odjemalca in objekt adapterja združljiva drug z drugim. Storitveni objekt tvori a has-a
odnos z objektom adapterja, tj. storitveni objekt pripada objektu adapterja.
Vemo, da servisni razred ni združljiv s stranko. Razred adapterja se ovije okoli storitvenega objekta tako, da se instancira s tem objektom. Zdaj lahko do storitvenega objekta dostopate prek objekta adapterja, kar odjemalcu omogoča interakcijo z njim.
Objektni adapter lahko implementiramo v vse sodobne programske jezike.
Razredni adapter
Pri tej metodi ima adapter is-a
razmerje s servisnim razredom. V tem scenariju adapter izvaja metode, ki jih zahteva odjemalec, vendar podeduje več prilagojenih elementov, kar mu daje možnost neposrednega klica njihovih nezdružljivih funkcij. Največja pomanjkljivost te različice je, da jo lahko uporabljamo samo v programskih jezikih, ki podpirajo večkratno dedovanje razredov.
Implementacija vzorca načrtovanja adapterja v Pythonu
V spodnjem razdelku bomo implementirali oblikovalski vzorec Adapter v Python, zlasti z uporabo različica adapterja objekta. Sekcija je razdeljena na dva dela. Najprej bomo ustvarili okolje, kjer bo uporabljen vzorec adapterja. Pomembno je jasno videti, kako lahko ta vzorec reši nekatere težave s programsko opremo. Drugi del bo za rešitev težave uporabil adapter.
Težava z nezdružljivostjo med razredi
Oglejmo si vprašanje združljivosti, ko odjemalec in storitveni razred implementirata različne funkcionalnosti. Ustvarite razred odjemalca z naslednjimi metodami in ga shranite v mapo kot 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")
Tukaj smo ustvarili a Car
razred s tremi metodami accelerate()
, apply_brakes()
in assign_driver()
. Uvozili smo random
modul in ga uporabil za ustvarjanje številk, ki določajo hitrost avtomobila po pospeševanju in zaviranju. The assign_driver()
prikaže ime voznika avtomobila.
Nato moramo ustvariti storitveni ali prilagojeni razred, ki želi sodelovati z razredom odjemalca Car
. Ustvarite razred motornih koles, kot je ta, in ga shranite v svojo mapo kot 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")
Servisni razred, Motorcycle
se ustvari zgoraj s tremi metodami rev_throttle()
, pull_brake_lever()
in assign_rider()
. Opazite razliko med metodama storitvenega in odjemalskega razreda kljub njuni podobni funkcionalnosti. The accelerator()
metoda poveča hitrost avtomobila, medtem ko rev_throttle()
metoda poveča hitrost motocikla. prav tako apply_brakes()
in pull_brake_lever()
zavira v ustreznih vozilih. Končno, assign_driver()
in assign_rider()
metode dodeli upravljavcu vozila.
Nato ustvarimo razred za dostop do teh različnih metod. Najprej dodajte __init.py__
v isti mapi, ki ste jo ustvarili car.py
in motorcycle.py
:
touch __init__.py
Zdaj dodajte naslednjo kodo v novo datoteko 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()
Ta skript, ki ustvari naše odjemalce in storitvene objekte. Najprej uvozimo Car
in Motorcycle
razrede in z njimi ustvarite predmete. Nato prikličemo metode iz bike
objekt (Motorcycle
razred). Nato prikličemo metode car
objekt (Car
razred). Ko se izvede, bo delovala vsa do sedaj omenjena koda.
Vendar se pojavi izjema, ko poskušamo priklicati metode Car
razred z bike
predmet. Ko zaženemo ta skript:
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'
V tem primeru lahko spremenimo Motorcycle
razred ali drive.py
skript za uporabo pravih metod. Vendar v mnogih primerih morda nimamo dostopa do izvorne kode odjemalca ali storitvenega razreda. Tudi to je preprost primer. Pri večjih odjemalcih in storitvah morda ne bo mogoče preoblikovati nobenega od njih, če prekinemo združljivost z drugimi sistemi.
Namesto tega lahko uporabimo adapter za premostitev vrzeli v združljivosti med našo odjemalsko kodo in našim storitvenim objektom.
Uporaba adapterjev za rešitev težave z nezdružljivostjo
V novi datoteki, motorcycle_adapter.py
, dodajte naslednji razred:
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)
Ustvarili smo a MotorcycleAdapter
razred, ki se instancira s storitvenim objektom (motorcycle
). Adapter izvaja odjemalske metode, ki so accelerate()
, apply_brakes()
in assign_driver()
. V notranjosti telesa accelerate()
metodo smo uporabili motorcycle
primerek storitvenega predmeta, ki ga želite poklicati rev_throttle()
način storitve. Podobno druge metode uporabljajo ustrezne metode Motorcycle
razred.
Zdaj pa posodobimo drive.py
tako da lahko uporabimo adapter v try/except
blok:
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()
Tubike_adapter
je predmet MotorcycleAdapter
razred. Dobavljali smo bike
nasprotovati MotorcycleAdapter
konstruktor razreda. Izvajanje tega skripta nam daje naslednje rezultate:
Oglejte si naš praktični, praktični vodnik za učenje Gita z najboljšimi praksami, standardi, sprejetimi v panogi, in priloženo goljufijo. Nehajte Googlati ukaze Git in pravzaprav naučiti it!
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
Brez prilagoditve osnovnega Motorcycle
razreda, ga lahko pripravimo, da deluje kot a Car
z uporabo adapterja!
Prednosti in slabosti vzorca načrtovanja adapterja
Prednosti vzorcev adapterjev so:
- Dosežemo lahko nizko povezavo med razredom adapterja in razredom odjemalca.
- Razred adapterja lahko ponovno uporabimo za vključitev številnih servisnih razredov v aplikacijo.
- Fleksibilnost programa lahko povečamo z uvedbo več adapterjev brez poseganja v kodo odjemalca
Slabosti vzorca adapterja so:
- Kompleksnost programa se poveča z dodatkom razreda adapterja in servisnega razreda.
- V programu se povečajo režijski stroški, saj se zahteve posredujejo iz enega razreda v drugega.
- Vzorec adapterja (adapter razreda) uporablja večkratno dedovanje, ki ga morda ne podpirajo vsi programski jeziki.
zaključek
V tem članku smo izvedeli več o vzorcu načrtovanja adapterja, njegovih vrstah in težavah, ki jih rešujejo. Implementirali smo vzorec adapterja v Python, tako da lahko komuniciramo z a Motorcycle
predmet, kot a Car
objekt z uporabo adapterja, tako da se vmesnik vsakega razreda ne spremeni.