Pola Desain Adaptor dengan Python

Pengantar

Grafik Pola Desain Adaptor adalah populer Pola Desain Struktural digunakan dalam rekayasa perangkat lunak. Panduan ini membahas bagaimana kita dapat mengimplementasikan Pola Desain Adaptor dengan Python.

Pola desain adalah solusi seperti template โ€“ resep praktis untuk memecahkan masalah umum yang berulang dalam pengembangan perangkat lunak. Pola Adaptor didasarkan pada konsep adaptor dunia nyata! Misalnya, pengisi daya laptop mungkin memiliki colokan 3-pin di ujungnya, tetapi soket dinding mungkin hanya soket 2-pin. Untuk mencolokkan pengisi daya 3-pin ke soket ini, kita memerlukan adaptor, yang menerima colokan 3-pin, dan beradaptasi antarmuka ke dalam 2-pin stopkontak.

Pengisi daya 2-pin dan pengisi daya 3-pin memiliki fungsi dasar yang sama (menghantarkan listrik dari stop kontak ke laptop), tetapi memiliki bentuk yang berbeda, dan seseorang dapat dengan mudah menyesuaikan ke yang lain. Setiap kali Anda memiliki komponen perangkat lunak dengan fungsi dasar yang sama tetapi bentuk yang berbeda, Anda dapat menerapkan Pola Desain Adaptor.

Pola Adaptor mengikuti prinsip yang tepat ini. Ini memungkinkan dua antarmuka yang tidak kompatibel untuk bekerja bersama tanpa memodifikasi internal setiap komponen. Ini dicapai dengan mengadaptasi satu antarmuka, ke antarmuka lainnya, secara eksternal.

Mari kita lihat beberapa terminologi dasar sebelum menyelam lebih dalam ke dunia Adaptor Patterns:

  • Antarmuka Klien: Antarmuka yang menentukan fungsi yang harus diimplementasikan klien.
  • Pelanggan: Kelas yang mengimplementasikan antarmuka klien.
  • Adaptee/Layanan: Kelas yang tidak kompatibel yang perlu berkolaborasi dengan antarmuka klien.
  • adaptor: Kelas yang memungkinkan kolaborasi antara layanan dan klien.

Berbagai Jenis Pola Adaptor

Pola desain adaptor dapat diimplementasikan dalam dua cara berbeda:

Adaptor Obyek

Dengan metode ini, kelas adaptor mengimplementasikan metode dari antarmuka klien. Dengan demikian, objek klien dan objek adaptor kompatibel satu sama lain. Objek layanan membentuk has-a hubungan dengan objek adaptor yaitu objek layanan milik objek adaptor.

Kita tahu bahwa kelas layanan tidak kompatibel dengan klien. Kelas adaptor membungkus objek layanan dengan membuat instance dirinya sendiri dengan objek itu. Sekarang, objek layanan dapat diakses melalui objek adaptor, memungkinkan klien untuk berinteraksi dengannya.

Kita dapat mengimplementasikan adaptor objek di semua bahasa pemrograman modern.

Adaptor Kelas

Dengan metode ini, adaptor memiliki is-a hubungan dengan kelas layanan. Dalam skenario ini, adaptor mengimplementasikan metode yang diperlukan oleh klien, tetapi mewarisi dari beberapa adaptor, memberikannya kemampuan untuk memanggil fungsi mereka yang tidak kompatibel secara langsung. Kelemahan terbesar dengan variasi ini adalah bahwa kita hanya dapat menggunakannya dalam bahasa pemrograman yang mendukung pewarisan berganda kelas.

Implementasi Pola Desain Adaptor dengan Python

Pada bagian di bawah ini, kami akan menerapkan pola desain Adaptor dengan Python, khususnya menggunakan variasi adaptor objek. Bagian ini dibagi menjadi dua bagian. Pertama, kita akan membuat lingkungan di mana Pola Adaptor harus digunakan. Sangat penting untuk melihat dengan jelas bagaimana pola ini dapat memecahkan beberapa masalah perangkat lunak. Bagian kedua akan menggunakan adaptor untuk menyelesaikan masalah.

Masalah Ketidakcocokan Antar Kelas

Mari kita lihat masalah kompatibilitas ketika klien dan kelas layanan mengimplementasikan fungsionalitas yang berbeda. Buat kelas klien dengan metode berikut dan simpan di folder sebagai 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")

Di sini, kami telah membuat Car kelas dengan tiga metode accelerate(), apply_brakes() dan assign_driver(). Kami mengimpor random modul dan menggunakannya untuk menghasilkan angka yang mengatur kecepatan mobil setelah berakselerasi dan mengerem. Itu assign_driver() metode menampilkan nama pengemudi mobil.

Selanjutnya kita harus membuat service atau kelas adaptee yang ingin berkolaborasi dengan kelas klien Car. Buat kelas Sepeda Motor seperti ini dan simpan di folder Anda sebagai 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")  

Sebuah kelas layanan, Motorcycle dibuat di atas dengan tiga metode rev_throttle(), pull_brake_lever(), dan assign_rider(). Perhatikan perbedaan antara metode layanan dan kelas klien meskipun fungsinya serupa. Itu accelerator() metode meningkatkan kecepatan mobil sementara rev_throttle() metode meningkatkan kecepatan sepeda motor. Juga, apply_brakes() dan pull_brake_lever() berlaku rem di kendaraan masing-masing. Akhirnya, assign_driver() dan assign_rider() metode menetapkan operator kendaraan.

Selanjutnya, mari buat kelas untuk mengakses metode yang berbeda ini. Pertama, tambahkan __init.py__ di folder yang sama yang Anda buat car.py dan motorcycle.py:

touch __init__.py

Sekarang tambahkan kode berikut di file baru 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()

Skrip ini yang membuat objek klien dan layanan kami. Kami pertama-tama mengimpor Car dan Motorcycle kelas dan membuat objek dengan mereka. Kemudian kita memanggil metode dari bike objek (Motorcycle kelas). Setelah itu, kita memanggil metode dari car objek (Car kelas). Saat dieksekusi, semua kode yang disebutkan sejauh ini akan berfungsi.

Namun, pengecualian muncul ketika kami mencoba memanggil metode dari Car kelas dengan bike obyek. Saat kami menjalankan skrip ini:

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'

Dalam hal ini, kita dapat memodifikasi Motorcycle kelas atau drive.py script untuk menggunakan metode yang tepat. Namun, dalam banyak kasus, kami mungkin tidak memiliki akses ke kode sumber klien atau kelas layanan. Juga, ini adalah contoh sederhana. Dengan klien dan layanan yang lebih besar, mungkin tidak layak untuk melakukan refactor salah satu dari mereka jika kita merusak kompatibilitas dengan sistem lain.

Sebagai gantinya, kita dapat menggunakan adaptor untuk menjembatani kesenjangan kompatibilitas antara kode klien dan objek layanan kita.

Menggunakan Adaptor untuk Memecahkan Masalah Ketidakcocokan

Dalam file baru, motorcycle_adapter.py, tambahkan kelas berikut:

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)

Kami menciptakan MotorcycleAdapter kelas, yang menginstansiasi dirinya dengan objek layanan (motorcycle). Adaptor mengimplementasikan metode klien yang accelerate(), apply_brakes() dan assign_driver(). Di dalam tubuh accelerate() metode, kami telah menggunakan motorcycle contoh objek layanan untuk memanggil rev_throttle() metode layanan. Demikian juga, metode lain menggunakan metode yang sesuai dari Motorcycle kelas.

Sekarang, mari kita perbarui drive.py jadi kita bisa menggunakan adaptor di 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()

Di sini,bike_adapter merupakan objek dari MotorcycleAdapter kelas. Kami menyediakan bike keberatan dengan MotorcycleAdapter konstruktor kelas. Menjalankan skrip ini memberi kita output berikut:

Lihat panduan praktis dan praktis kami untuk mempelajari Git, dengan praktik terbaik, standar yang diterima industri, dan termasuk lembar contekan. Hentikan perintah Googling Git dan sebenarnya belajar itu!

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

Tanpa harus menyesuaikan yang mendasarinya Motorcycle kelas, kita bisa membuatnya bekerja seperti Car menggunakan adaptor!

Pro dan Kontra Pola Desain Adaptor

Keuntungan dari Pola Adaptor adalah:

  • Kita dapat mencapai kopling rendah antara kelas adaptor dan kelas klien.
  • Kita dapat menggunakan kembali kelas adaptor untuk menggabungkan banyak kelas layanan dalam aplikasi.
  • Kami dapat meningkatkan fleksibilitas program dengan memperkenalkan beberapa adaptor tanpa mengganggu kode klien

Kerugian dari Pola Adaptor adalah:

  • Kompleksitas program meningkat dengan penambahan kelas adaptor dan kelas layanan.
  • Ada peningkatan overhead dalam program karena permintaan diteruskan dari satu kelas ke kelas lainnya.
  • Pola Adaptor (adaptor kelas) menggunakan banyak pewarisan, yang mungkin tidak didukung oleh semua bahasa pemrograman.

Kesimpulan

Dalam artikel ini, kita mempelajari tentang pola desain adaptor, jenisnya, dan masalah yang dipecahkannya. Kami menerapkan Pola Adaptor dengan Python sehingga kami dapat berinteraksi dengan a Motorcycle objek, seperti Car objek dengan menggunakan adaptor sehingga antarmuka setiap kelas tidak berubah.

Stempel Waktu:

Lebih dari penyalahgunaan