Μοτίβο σχεδίασης προσαρμογέα στην Python

Εισαγωγή

Η Μοτίβο σχεδίασης προσαρμογέα είναι δημοφιλής Μοτίβο δομικής σχεδίασης χρησιμοποιείται στη μηχανική λογισμικού. Αυτός ο οδηγός εξετάζει πώς μπορούμε να εφαρμόσουμε το μοτίβο σχεδίασης προσαρμογέα στην Python.

Σχεδιαστικά πρότυπα είναι λύσεις που μοιάζουν με πρότυπα – πρακτικά συνταγές για την επίλυση επαναλαμβανόμενων, κοινών προβλημάτων στην ανάπτυξη λογισμικού. Το μοτίβο προσαρμογέα βασίζεται στην ιδέα ενός προσαρμογέα πραγματικού κόσμου! Για παράδειγμα, ο φορτιστής ενός φορητού υπολογιστή μπορεί να έχει ένα βύσμα 3 ακίδων στο άκρο, αλλά η πρίζα μπορεί να είναι μόνο μια πρίζα 2 ακίδων. Για να συνδέσουμε έναν φορτιστή 3 ακίδων σε αυτήν την πρίζα, θα χρειαστούμε έναν προσαρμογέα που δέχεται βύσμα 3 ακίδων και προσαρμόζεται τη διεπαφή στο 2-pin πρίζα.

Ένας φορτιστής 2 ακίδων και ένας φορτιστής 3 ακίδων διαθέτουν την ίδια βασική λειτουργία (πραγματοποίηση ηλεκτρικής ενέργειας από την πρίζα στο φορητό υπολογιστή), αλλά έχουν διαφορετική μορφή, και μπορεί κανείς εύκολα προσαρμόσει στο άλλο. Κάθε φορά που έχετε στοιχεία λογισμικού με την ίδια βασική λειτουργία αλλά διαφορετικές φόρμες, μπορείτε να εφαρμόσετε το μοτίβο σχεδίασης προσαρμογέα.

Το μοτίβο προσαρμογέα ακολουθεί αυτήν ακριβώς την αρχή. Επιτρέπει σε δύο μη συμβατές διεπαφές να συνεργάζονται χωρίς να τροποποιούνται τα εσωτερικά κάθε στοιχείου. Αυτό επιτυγχάνεται με την προσαρμογή μιας διεπαφής, σε μια άλλη, εξωτερικά.

Ας δούμε κάποια βασική ορολογία πριν βουτήξουμε βαθύτερα στον κόσμο των μοτίβων προσαρμογέων:

  • Διεπαφή πελάτη: Μια διεπαφή που καθορίζει τις λειτουργίες που πρέπει να υλοποιήσει ο πελάτης.
  • Πελάτης: Μια κλάση που υλοποιεί τη διεπαφή πελάτη.
  • Προσαρμοσμένος/Υπηρεσία: Η μη συμβατή κλάση που χρειάζεται να συνεργαστεί με τη διεπαφή πελάτη.
  • Προσαρμογέας: Η κλάση που καθιστά δυνατή τη συνεργασία μεταξύ της υπηρεσίας και του πελάτη.

Διαφορετικοί τύποι μοτίβων προσαρμογέων

Το σχέδιο σχεδίασης προσαρμογέα μπορεί να εφαρμοστεί με δύο διαφορετικούς τρόπους:

Προσαρμογέας αντικειμένων

Με αυτήν τη μέθοδο, η κλάση προσαρμογέα υλοποιεί τις μεθόδους από τη διεπαφή πελάτη. Έτσι, το αντικείμενο πελάτη και το αντικείμενο προσαρμογέα είναι συμβατά μεταξύ τους. Το αντικείμενο υπηρεσίας σχηματίζει α has-a σχέση με το αντικείμενο προσαρμογέα, δηλαδή το αντικείμενο υπηρεσίας ανήκει στο αντικείμενο προσαρμογέα.

Γνωρίζουμε ότι η κατηγορία υπηρεσιών δεν είναι συμβατή με τον πελάτη. Η κλάση προσαρμογέα τυλίγεται γύρω από το αντικείμενο υπηρεσίας εγκαθιστώντας τον εαυτό της με αυτό το αντικείμενο. Τώρα, το αντικείμενο υπηρεσίας μπορεί να προσπελαστεί μέσω του αντικειμένου προσαρμογέα, επιτρέποντας στον πελάτη να αλληλεπιδράσει μαζί του.

Μπορούμε να εφαρμόσουμε τον προσαρμογέα αντικειμένων σε όλες τις σύγχρονες γλώσσες προγραμματισμού.

Προσαρμογέας κλάσης

Με αυτή τη μέθοδο, ο προσαρμογέας έχει ένα is-a σχέση με την κατηγορία υπηρεσιών. Σε αυτό το σενάριο, ο προσαρμογέας εφαρμόζει τις μεθόδους που απαιτούνται από τον πελάτη, αλλά κληρονομεί από πολλαπλούς προσαρμογείς, δίνοντάς του τη δυνατότητα να καλεί απευθείας τις μη συμβατές συναρτήσεις τους. Το μεγαλύτερο μειονέκτημα αυτής της παραλλαγής είναι ότι μπορούμε να τη χρησιμοποιήσουμε μόνο στις γλώσσες προγραμματισμού που υποστηρίζουν πολλαπλή κληρονομικότητα κλάσεων.

Υλοποίηση του μοτίβου σχεδίασης προσαρμογέα στην Python

Στην παρακάτω ενότητα, θα εφαρμόσουμε το μοτίβο σχεδίασης προσαρμογέα στην Python, χρησιμοποιώντας συγκεκριμένα το παραλλαγή προσαρμογέα αντικειμένου. Η ενότητα χωρίζεται σε δύο μέρη. Αρχικά, θα δημιουργήσουμε το περιβάλλον όπου θα πρέπει να χρησιμοποιηθεί το μοτίβο προσαρμογέα. Είναι σημαντικό να δούμε ξεκάθαρα πώς αυτό το μοτίβο μπορεί να λύσει ορισμένα προβλήματα λογισμικού. Η δεύτερη ενότητα θα χρησιμοποιήσει έναν προσαρμογέα για την επίλυση του προβλήματος.

Ζήτημα ασυμβατότητας μεταξύ τάξεων

Ας δούμε το ζήτημα της συμβατότητας όταν ο πελάτης και η κατηγορία υπηρεσιών εφαρμόζουν διαφορετικές λειτουργίες. Δημιουργήστε μια κλάση πελάτη με τις ακόλουθες μεθόδους και αποθηκεύστε την σε ένα φάκελο ως 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")

Εδώ, δημιουργήσαμε ένα Car τάξη με τρεις μεθόδους accelerate(), apply_brakes() και assign_driver(). Εισαγάγαμε το random μονάδα και τη χρησιμοποίησε για να δημιουργήσει αριθμούς που καθορίζουν την ταχύτητα του αυτοκινήτου μετά την επιτάχυνση και το πάτημα των φρένων. ο assign_driver() μέθοδος εμφανίζει το όνομα του οδηγού του αυτοκινήτου.

Στη συνέχεια, πρέπει να δημιουργήσουμε μια κλάση υπηρεσίας ή προσαρμοσμένου που επιθυμεί να συνεργαστεί με την κλάση πελάτη Car. Δημιουργήστε μια κατηγορία μοτοσυκλετών όπως αυτή και αποθηκεύστε την στον φάκελό σας ως 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")  

Μια κατηγορία υπηρεσιών, Motorcycle δημιουργείται παραπάνω με τρεις μεθόδους rev_throttle(), pull_brake_lever(), να assign_rider(). Παρατηρήστε τη διαφορά μεταξύ των μεθόδων της κλάσης υπηρεσίας και πελάτη παρά την παρόμοια λειτουργικότητά τους. ο accelerator() μέθοδος αυξάνει την ταχύτητα του αυτοκινήτου ενώ η rev_throttle() μέθοδος αυξάνει την ταχύτητα της μοτοσυκλέτας. Επίσης, apply_brakes() και pull_brake_lever() φρενάρει στα αντίστοιχα οχήματα. Τέλος, το assign_driver() και assign_rider() μέθοδοι εκχωρούν στον χειριστή του οχήματος.

Στη συνέχεια, ας δημιουργήσουμε μια κλάση για πρόσβαση σε αυτές τις διαφορετικές μεθόδους. Αρχικά, προσθέστε ένα __init.py__ στον ίδιο φάκελο που δημιουργήσατε car.py και motorcycle.py:

touch __init__.py

Τώρα προσθέστε τον ακόλουθο κώδικα σε ένα νέο αρχείο 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()

Αυτό το σενάριο που δημιουργεί αντικείμενα πελάτη και υπηρεσίας. Εισάγουμε πρώτα το Car και Motorcycle τάξεις και να δημιουργήσετε αντικείμενα με αυτές. Στη συνέχεια επικαλούμαστε τις μεθόδους από το bike αντικείμενο (Motorcycle τάξη). Μετά, επικαλούμαστε τις μεθόδους του car αντικείμενο (Car τάξη). Όταν εκτελεστεί, όλος ο κώδικας που αναφέρεται μέχρι τώρα θα λειτουργήσει.

Ωστόσο, εγείρεται μια εξαίρεση όταν προσπαθούμε να επικαλεστούμε τις μεθόδους του Car τάξη με το bike αντικείμενο. Όταν εκτελούμε αυτό το σενάριο:

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'

Σε αυτήν την περίπτωση, μπορούμε να τροποποιήσουμε το Motorcycle τάξη ή το drive.py script για να χρησιμοποιήσετε τις σωστές μεθόδους. Ωστόσο, σε πολλές περιπτώσεις, ενδέχεται να μην έχουμε πρόσβαση στον πηγαίο κώδικα της κλάσης πελάτη ή υπηρεσίας. Επίσης, αυτό είναι ένα απλό παράδειγμα. Με μεγαλύτερους πελάτες και υπηρεσίες, ενδέχεται να μην είναι εφικτή η αναμόρφωση κανενός από τους δύο σε περίπτωση διακοπής της συμβατότητας με άλλα συστήματα.

Αντίθετα, μπορούμε να χρησιμοποιήσουμε έναν προσαρμογέα για να γεφυρώσει το χάσμα συμβατότητας μεταξύ του κώδικα πελάτη μας και του αντικειμένου υπηρεσίας μας.

Χρήση προσαρμογέων για την επίλυση του ζητήματος ασυμβατότητας

Σε νέο αρχείο, motorcycle_adapter.py, προσθέστε την ακόλουθη κλάση:

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)

Δημιουργήσαμε μια MotorcycleAdapter κλάση, η οποία εγκαινιάζεται με ένα αντικείμενο υπηρεσίας (motorcycle). Ο προσαρμογέας υλοποιεί τις μεθόδους πελάτη που είναι accelerate(), apply_brakes() και assign_driver(). Μέσα στο σώμα του accelerate() μέθοδο, χρησιμοποιήσαμε το motorcycle παρουσία του αντικειμένου υπηρεσίας για κλήση του rev_throttle() μέθοδος εξυπηρέτησης. Ομοίως, οι άλλες μέθοδοι χρησιμοποιούν τις αντίστοιχες μεθόδους του Motorcycle τάξη.

Τώρα, ας ενημερώσουμε drive.py ώστε να μπορούμε να χρησιμοποιήσουμε τον προσαρμογέα στο try/except block:

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()

Εδώ,bike_adapter είναι αντικείμενο του MotorcycleAdapter τάξη. Προμηθεύσαμε το bike αντίρρηση στο MotorcycleAdapter κατασκευαστής της τάξης. Η εκτέλεση αυτής της δέσμης ενεργειών μας δίνει την ακόλουθη έξοδο:

Ρίξτε μια ματιά στον πρακτικό μας οδηγό για την εκμάθηση του Git, με βέλτιστες πρακτικές, πρότυπα αποδεκτά από τον κλάδο και συμπεριλαμβανόμενο φύλλο εξαπάτησης. Σταματήστε τις εντολές του Git στο Google και πραγματικά μαθαίνουν το!

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

Χωρίς να χρειάζεται να προσαρμόσετε το υποκείμενο Motorcycle τάξη, μπορούμε να το κάνουμε να λειτουργήσει σαν α Car χρησιμοποιώντας έναν προσαρμογέα!

Πλεονεκτήματα και μειονεκτήματα του μοτίβου σχεδίασης προσαρμογέα

Τα πλεονεκτήματα των μοτίβων προσαρμογέων είναι:

  • Μπορούμε να επιτύχουμε χαμηλή σύζευξη μεταξύ της κατηγορίας προσαρμογέα και της κατηγορίας πελάτη.
  • Μπορούμε να χρησιμοποιήσουμε ξανά την κλάση προσαρμογέα για να ενσωματώσουμε πολλές κατηγορίες υπηρεσιών στην εφαρμογή.
  • Μπορούμε να αυξήσουμε την ευελιξία του προγράμματος εισάγοντας πολλαπλούς προσαρμογείς χωρίς παρεμβολές στον κώδικα πελάτη

Τα μειονεκτήματα του μοτίβου προσαρμογέα είναι:

  • Η πολυπλοκότητα του προγράμματος αυξάνεται με την προσθήκη της κατηγορίας προσαρμογέα και της κατηγορίας υπηρεσιών.
  • Υπάρχει μια αύξηση των γενικών εξόδων στο πρόγραμμα καθώς τα αιτήματα προωθούνται από τη μια τάξη στην άλλη.
  • Το μοτίβο προσαρμογέα (προσαρμογέας κλάσης) χρησιμοποιεί πολλαπλές κληρονομιές, τις οποίες ενδέχεται να μην υποστηρίζουν όλες οι γλώσσες προγραμματισμού.

Συμπέρασμα

Σε αυτό το άρθρο, μάθαμε για το μοτίβο σχεδίασης προσαρμογέα, τους τύπους του και τα προβλήματα που επιλύουν. Υλοποιήσαμε το μοτίβο προσαρμογέα στην Python ώστε να μπορούμε να αλληλεπιδράσουμε με ένα Motorcycle αντικείμενο, όπως α Car αντικείμενο χρησιμοποιώντας έναν προσαρμογέα, ώστε η διεπαφή κάθε κλάσης να μην αλλάζει.

Σφραγίδα ώρας:

Περισσότερα από Stackabuse