Pola Desain Strategi

Dec 01 2022
merangkum apa yang bervariasi
Katakanlah kita memiliki aplikasi yang memungkinkan pelanggan membayar untuk membeli produk atau mendapatkan layanan. Aplikasi memiliki lebih dari satu cara pembayaran, pelanggan dapat menggunakan uang tunai, kartu visa atau dompet, kami dapat melakukannya seperti ini: Sebenarnya tidak, Kami memiliki tiga jenis pembayaran dan dalam setiap kasus ada penerapan yang berbeda sehingga kami memiliki satu perilaku "membayar" dengan cara yang berbeda, jadi apa yang bisa terjadi jika kita mengambil apa yang bervariasi dan meletakkannya di kelas terpisah dan menggunakan antarmuka umum untuk perilaku umum.

Katakanlah kita memiliki aplikasi yang memungkinkan pelanggan membayar untuk membeli produk atau mendapatkan layanan.

Aplikasi ini memiliki lebih dari satu cara pembayaran, pelanggan bisa menggunakan uang tunai, kartu visa atau dompet, kita bisa melakukannya seperti ini:

public class Customer {

  public void pay(String paymentType) {
    if (StringUtils.isEmpty(paymentType)) {
      throw new RuntimeException("please add payment method");
    }
      // pay according to payment type
    if (paymentType.equalsIgnoreCase("cash")) {
      // pay in cash steps ( Algorithm )
    } else if (paymentType.equalsIgnoreCase("visa")) {
      // use the visa for payment steps ( Algorithm )
    } else if (paymentType.equalsIgnoreCase("wallet")) {
      // use the wallet for payment steps ( Algorithm )
    } else {
      throw new RuntimeException(paymentType + "payment type is not available");
    }
  }
}

public class Client {
    public static void main(String[] args) {
        Customer customer = new Customer();
        customer.pay("cash");
    }
}

Sebenarnya tidak,

  1. Jika Anda ingin menambahkan metode pembayaran baru, maka Anda perlu mengubah kelas ini, dan itu membuat desain Anda tidak fleksibel untuk setiap perubahan baru, dengan penerapan ini kami melanggar salah satu prinsip desain SOLID yaitu: “ entitas perangkat lunak harus terbuka untuk perpanjangan tetapi ditutup untuk modifikasi
  2. Sebagian besar logika di kelas tidak digunakan, setelah jenis pembayaran dipilih oleh klien, jadi jika klien ingin membayar tunai maka kode yang menangani visa dan dompet tidak akan digunakan.
  3. Seperti yang Anda lihat dalam cara desain ini, Anda harus menangani setiap input jenis pembayaran yang memungkinkan meskipun tidak masuk akal, sebagai jenis pembayaran NULL, atau jenis pembayaran kosong, dan Anda dapat dengan mudah membatasi klien untuk hanya memilih jenis pembayaran yang valid , dengan menggunakan pola strategi.

Kami memiliki tiga jenis pembayaran dan dalam setiap kasus ada implementasi yang berbeda sehingga kami memiliki satu perilaku "bayar" dengan cara yang berbeda, jadi apa yang bisa terjadi jika kami mengambil apa yang bervariasi dan meletakkannya di kelas terpisah dan menggunakan antarmuka umum untuk perilaku umum tersebut .

Mari kita buat antarmuka yang disebut Pembayaran . Ini akan memiliki metode abstrak, dan setiap metode pembayaran memiliki kelas konkret yang mengimplementasikan antarmuka Pembayaran . Pelanggan akan memiliki antarmuka pembayaran sebagai variabel "komposisi penggunaan" dan metode jenis akan ditentukan oleh pilihan klien.

public interface Payment {
    void pay();
}
public class CashPayment implements Payment {
    @Override
    public void pay() {
        // pay in cash steps ( Algorithm )
    }
}
public class VisaPayment implements Payment {
    @Override
    public void pay() {
        // use the visa for payment steps ( Algorithm )
    }
}
public class WalletPayment implements Payment {
    @Override
    public void pay() {
        // use the wallet for payment steps ( Algorithm )
    }
}

public class Customer {
    private Payment payment;

    public Customer(Payment payment) {
        this.payment = payment;
    }

    public void setPaymentType(Payment payment) {
        this.payment = payment;
    }

    public void pay() {
        payment.pay();
    }
}

public class Client {
    public static void main(String[] args) {
        Customer customer = new Customer(new VisaPayment());
        customer.pay();
        // you can change the payment type at runtime
        customer.setPaymentType(new CashPayment());
        customer.pay();
    }
}

Diagram UML untuk contoh pembayaran pelanggan

Prinsip desain

dari pembahasan sebelumnya kita dapat menyimpulkan empat prinsip desain:

  1. Desain untuk antarmuka bukan untuk implementasi
  2. Merangkum apa yang bervariasi
  3. Entitas perangkat lunak harus terbuka untuk ekstensi tetapi tertutup untuk modifikasi
  4. Gunakan komposisi di atas warisan

Definisi buku untuk pola strategi adalah: Mendefinisikan keluarga algoritma, merangkum masing-masing, dan membuatnya dapat dipertukarkan. Strategi memungkinkan algoritme bervariasi secara independen dari klien yang menggunakannya.

Dalam contoh kami keluarga algoritme adalah metode pembayaran, dan kami merangkum masing-masing dari mereka dalam subkelas konkret, dan mereka dapat dipertukarkan oleh klien yang dapat memilih jenis pembayaran apa pun bahkan saat runtime, algoritme dipisahkan dari Pelanggan dan Klien …. dan itulah pola strateginya .