引言
在我们之前的讨论中,我们探索了工厂方法模式——一种简化单一产品创建的设计模式。现在,我们将视角转向抽象工厂模式,这是一种更高层次的设计模式,用于管理和创建一系列相关的产品。
抽象工厂模式简介
定义与用途
抽象工厂模式是创建型设计模式的一个高级形式,它允许生成一系列相关或相互依赖的对象。与工厂方法模式相比,抽象工厂模式在创建多种相关产品时提供了更大的灵活性和扩展性。
实现方式:
通过定义一个中心化的工厂类接口来创建一组相关或相互依赖的对象,而具体的创建逻辑由实现该接口的具体工厂类完成。
使用场景
- 管理相关对象的家族:当需要创建一组执行相似功能但具有不同变体的对象时,例如不同类型的用户界面组件。
- 系统配置对客户端透明:当客户端不需要知道它使用的具体实现细节,只关心接口时。
- 动态切换产品系列:在运行时切换不同的实现(如不同的数据库平台或操作系统环境)而不影响客户端代码。
- 强调平台独立性和一致性:当系统需要在不同的环境中提供一致的操作,并保持与平台的独立性时。
优势与劣势
- 优势
提高了系统的抽象性和可维护性:客户端代码只与抽象工厂和产品接口交互,提高了系统的灵活性。
增强了系统的扩展性:可以轻松添加新的产品族,而无需修改现有代码。 - 劣势
增加了系统的复杂性:由于引入了多个接口和类。
扩展新种类的产品难度较高:添加新产品需要修改抽象工厂接口。
抽象工厂模式在spring中的应用
- Spring中的BeanFactory和它的扩展ApplicationContext是抽象工厂模式的经典应用。它们提供了一个高级的工厂接口来创建应用中的对象和服务。
- ApplicationContext通过读取配置文件来创建和管理bean,而这些bean可以被视为产品,Spring容器(工厂)管理着它们的整个生命周期。
- FactoryBean 接口:Spring中的FactoryBean接口是抽象工厂模式的另一个应用。实现了FactoryBean的类负责产生其他bean的实例。
这允许实现复杂的初始化逻辑,或者返回一个与实现类逻辑不同的对象实例。
银行和贷款服务示例
- 我们将创建一个银行接口(Bank interface)和一个贷款抽象类(Loan abstract class)以及它们的子类。
- 接着,我们将创建一个抽象工厂类(AbstractFactory class)
我们将创建具体的类,银行工厂(BankFactory)和贷款工厂(LoanFactory),这些类将继承抽象工厂类。 - 抽象工厂模式示例类(AbstractFactoryPatternExample class)使用工厂创造器(FactoryCreator)来获取抽象工厂类的对象。
步骤 1: 创建银行接口
public interface Bank {
String getBankName();
}
步骤 2: 实现银行接口的具体类
class HDFC implements Bank{
private final String BNAME;
public HDFC(){
BNAME="HDFC BANK";
}
@Override
public String getBankName() {
return BNAME;
}
}
class ICICI implements Bank{
private final String BNAME;
ICICI(){
BNAME="ICICI BANK";
}
@Override
public String getBankName() {
return BNAME;
}
}
class SBI implements Bank{
private final String BNAME;
public SBI(){
BNAME="SBI BANK";
}
@Override
public String getBankName(){
return BNAME;
}
}
步骤 3: 创建贷款抽象类
public abstract class Loan {
protected double rate;
abstract void getInterestRate(double rate);
public void calculateLoanPayment(double loanamount, int years)
{
/*
to calculate the monthly loan payment i.e. EMI
rate=annual interest rate/12*100;
n=number of monthly installments;
1year=12 months.
so, 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 +" 贷款总额:"+loanamount+"");
}
}
步骤 4: 继承贷款抽象类的具体类
//家庭贷款
class HomeLoan extends Loan {
@Override
public void getInterestRate(double r){
rate=r;
}
}
//商业贷款
class BussinessLoan extends Loan{
@Override
public void getInterestRate(double r){
rate=r;
}
}
//教育贷款
class EducationLoan extends Loan{
@Override
public void getInterestRate(double r){
rate=r;
}
}
步骤 5: 创建抽象工厂类
public abstract class AbstractFactory {
public abstract Bank getBank(String bank);
public abstract Loan getLoan(String loan);
}
步骤 6: 创建继承AbstractFactory类的工厂类,根据给定的信息生成具体类的对象。
public class BankFactory extends AbstractFactory{
@Override
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;
}
@Override
public Loan getLoan(String loan) {
return null;
}
}
public class LoanFactory extends AbstractFactory{
@Override
public Bank getBank(String bank){
return null;
}
@Override
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;
}
}
**步骤 7:**创建一个FactoryCreator类,通过传递Bank或Loan之类的信息来获取工厂。
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;
}
}
**步骤 8:**使用FactoryCreator获取AbstractFactory,以便通过传递类型等信息来获取具体类的工厂。
public class AbstractFactoryPatternExample {
public static void main(String args[]) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("输入你想贷款银行的名称: ");
String bankName = br.readLine();
System.out.print("\n");
System.out.print("输入你想贷款的类型: ");
String loanName = br.readLine();
AbstractFactory bankFactory = FactoryCreator.getFactory("Bank");
Bank b = bankFactory.getBank(bankName);
System.out.print("\n");
System.out.print("输入利率 " + b.getBankName() + ": ");
double rate = Double.parseDouble(br.readLine());
System.out.print("\n");
System.out.print("输入贷款金额: ");
double loanAmount = Double.parseDouble(br.readLine());
System.out.print("\n");
System.out.print("输入贷款年限: ");
int years = Integer.parseInt(br.readLine());
System.out.print("\n");
System.out.println("你正在从银行贷款 " + b.getBankName());
AbstractFactory loanFactory = FactoryCreator.getFactory("Loan");
Loan l = loanFactory.getLoan(loanName);
l.getInterestRate(rate);
l.calculateLoanPayment(loanAmount, years);
}
}
以上就是一个简单的抽象工厂示例代码,运行代码我们可以看到:
输入相应的数据就可以算出不同银行,不同贷款类型下具体贷款明细了。
代码地址
23种设计模式相关代码后续会逐步提交到github上,方便学习,欢迎指点:
代码地址
https://github.com/RuofeiSun/lf-23Pattern