Mẫu thiết kế Abstract Factory nói rằng chỉ cần định nghĩa một interface hoặc lớp trừu tượng (abstract) để tạo ra các họ hàng của các đối tượng liên quan (hoặc phụ thuộc) mà không cần chỉ rõ các lớp con cụ thể của chúng. Điều này có nghĩa là mẫu thiết kế Abstract Factory cho phép một lớp trả về một nhà máy của các lớp. Vì vậy, đây là lý do mà mẫu thiết kế Abstract Factory cao hơn một cấp so với mẫu thiết kế Factory Method.
Nội dung chính
Lợi thế của mẫu thiết kế Abstract Factory
- Mẫu thiết kế Abstract Factory cô lập mã khách hàng từ các lớp cụ thể.
- Nó giúp giảm bớt sự trao đổi của các gia đình đối tượng.
- Nó thúc đẩy sự nhất quán giữa các đối tượng.
Cách sử dụng mẫu thiết kế Abstract Factory
- Khi hệ thống cần phải độc lập với cách đối tượng của nó được tạo ra.
- Khi gia đình của các đối tượng liên quan phải được sử dụng cùng nhau, thì ràng buộc này cần được thực thi.
- Khi bạn muốn cung cấp một thư viện các đối tượng không hiển thị các triển khai chi tiết và chỉ lộ các giao diện.
- Khi hệ thống cần được cấu hình với một trong nhiều họ đối tượng.
UML cho mẫu thiết kế Abstract Factory
- Chúng ta sẽ tạo ra một interface Bank và một lớp trừu tượng Loan và các lớp con của chúng.
- Sau đó chúng ta sẽ tạo lớp AbstractFactory trong bước tiếp theo.
- Sau đó, sau khi chúng ta sẽ tạo các lớp cụ thể, BankFactory và LoanFactory sẽ extends lớp AbstractFactory.
- Sau đó, lớp AbstractFactoryPatternExample sử dụng FactoryCreator để lấy một đối tượng của lớp AbstractFactory.
- Hãy xem biểu đồ UML của trường hợp trên được đưa ra dưới đây:
Ví dụ mẫu thiết kế Abstract Factory
Ở đây, chúng tôi tính toán khoản thanh toán khoản vay cho các ngân hàng khác nhau như HDFC, ICICI, SBI.
Bước 1: tạo interface Bank
package vn.kienthuclaptrinh.designpattern; public interface Bank { String getBankName(); }
Bước 2: Tạo các lớp cụ thể để triển khai interface Bank
Lớp HDFC.java
package vn.kienthuclaptrinh.designpattern; public class HDFC implements Bank { private final String BNAME; public HDFC() { BNAME = "HDFC BANK"; } public String getBankName() { return BNAME; } }
Lớp ICICI.java
package vn.kienthuclaptrinh.designpattern; public class ICICI implements Bank { private final String BNAME; ICICI() { BNAME = "ICICI BANK"; } public String getBankName() { return BNAME; } }
Lớp SBI.java
package vn.kienthuclaptrinh.designpattern; public class SBI implements Bank { private final String BNAME; public SBI() { BNAME = "SBI BANK"; } public String getBankName() { return BNAME; } }
Bước 3: Tạo lớp abstract Loan
package vn.kienthuclaptrinh.designpattern; public abstract class Loan { protected double rate; abstract void getInterestRate(double rate); public void calculateLoanPayment(double loanAmount, int years) { /* * tính toán khoản thanh toán tiền vay hàng tháng * * rate = (lãi suất năm / 12) * 100; * n = số lần trả góp hàng tháng; * 1year = 12 months, * n = years * 12; */ double EMI; int n; n = years * 12; rate = rate / 1200; EMI = ((rate * Math.pow((1 + rate), n)) / ((Math.pow((1 + rate), n)) - 1)) * loanAmount; System.out.println("EMI hang thang cua ba la: " + EMI + " cho so luong " + loanAmount + " ban da vay."); } }
Bước 4: Tạo các lớp cụ thể extends từ lớp abstract Loan
Lớp HomeLoan.java
package vn.kienthuclaptrinh.designpattern; public class HomeLoan extends Loan { public void getInterestRate(double r) { rate = r; } }
Lớp BussinessLoan.java
package vn.kienthuclaptrinh.designpattern; public class BussinessLoan extends Loan { public void getInterestRate(double r) { rate = r; } }
Lớp EducationLoan.java
package vn.kienthuclaptrinh.designpattern; public class EducationLoan extends Loan { public void getInterestRate(double r) { rate = r; } }
Bước 5: Tạo một lớp trừu tượng (tức là AbstractFactory) để lấy các nhà máy cho Bank và các đối tượng Loan.
package vn.kienthuclaptrinh.designpattern; public abstract class AbstractFactory { public abstract Bank getBank(String bank); public abstract Loan getLoan(String loan); }
Bước 6: Tạo các lớp nhà máy kế thừa lớp AbstractFactory để tạo đối tượng của lớp cụ thể dựa trên thông tin đã cho.
Lớp BankFactory.java
package vn.kienthuclaptrinh.designpattern; public class BankFactory extends AbstractFactory { public Bank getBank(String bank) { if (bank == null) { return null; } if (bank.equalsIgnoreCase("HDFC")) { return new HDFC(); } else if (bank.equalsIgnoreCase("ICICI")) { return new ICICI(); } else if (bank.equalsIgnoreCase("SBI")) { return new SBI(); } return null; } public Loan getLoan(String loan) { return null; } }
Lớp LoanFactory.java
package vn.kienthuclaptrinh.designpattern; public class LoanFactory extends AbstractFactory { public Bank getBank(String bank) { return null; } public Loan getLoan(String loan) { if (loan == null) { return null; } if (loan.equalsIgnoreCase("Home")) { return new HomeLoan(); } else if (loan.equalsIgnoreCase("Business")) { return new BussinessLoan(); } else if (loan.equalsIgnoreCase("Education")) { return new EducationLoan(); } return null; } }
Bước 7: Tạo một lớp FactoryCreator để nhận các nhà máy bằng cách chuyển một thông tin như Bank hoặc Loan.
package vn.kienthuclaptrinh.designpattern; public class FactoryCreator { public static AbstractFactory getFactory(String choice) { if (choice.equalsIgnoreCase("Bank")) { return new BankFactory(); } else if (choice.equalsIgnoreCase("Loan")) { return new LoanFactory(); } return null; } }
Bước 8: Sử dụng FactoryCreator để lấy AbstractFactory để nhận các nhà máy của các lớp cụ thể bằng cách truyền một thông tin "Bank" hoặc "Loan".
package vn.kienthuclaptrinh.designpattern; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class AbstractFactoryPatternExample { public static void main(String args[]) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Nhap ten cua Bank ma ban muon vay tien: "); String bankName = br.readLine(); System.out.print("Nhap kieu ban muon vay (home, business, education): "); String loanName = br.readLine(); AbstractFactory bankFactory = FactoryCreator.getFactory("Bank"); Bank b = bankFactory.getBank(bankName); System.out.print("Nhap lai suat ngan hang " + b.getBankName() + ": "); double rate = Double.parseDouble(br.readLine()); System.out.print("Nhap so tien ban muon vay: "); double loanAmount = Double.parseDouble(br.readLine()); System.out.print("Nhap so nam de thanh toan toan bo so tien ban vay: "); int years = Integer.parseInt(br.readLine()); System.out.println("Ban dang vay tien tu " + b.getBankName()); AbstractFactory loanFactory = FactoryCreator.getFactory("Loan"); Loan loan = loanFactory.getLoan(loanName); loan.getInterestRate(rate); loan.calculateLoanPayment(loanAmount, years); } }
Kết quả:
Nhap kieu ban muon vay (home, business, education): home Nhap lai suat ngan hang SBI BANK: 10 Nhap so tien ban muon vay: 100000000 Nhap so nam de thanh toan toan bo so tien ban vay: 5 Ban dang vay tien tuSBI BANK EMI hang thang cua ba la: 2124704.471126833 cho so luong 1.0E8 ban da vay.