一. 抽象工厂模式的基本介绍
意图
提供一个创建一系列或相互依赖对象的接口,而无需指定它们具体的类。
结构
抽象工厂模式的基本结构如下:
这里涉及到的参与者有如下几种:
- 抽象工厂(AbstractFcatory)角色
- 声明一个创建抽象产品对象的操作接口。
- 具体工厂(ConcreteFactory)角色
- 实现创建具体产品对象的操作。
- 抽象产品(AbstractProduct)角色
- 为一类产品对象声明一个接口
- 具体产品(ConcreteProduct)角色
- 定义一个将被相应的具体工厂创建的产品对象
- 实现AbstractProduct接口
- 抽象工厂(AbstractFcatory)角色
- 仅使用由AbstractFactory和AbstractProduct类声明的接口
二. 抽象工厂模式的示例
接下来,我们创建两个产品族,一个是Bank,一个Loan,使用抽象工厂创建银行和贷款对象。
- 抽象产品Bank和Loan
package com.wangmengjun.tutorial.designpattern.abstractfactory;
public interface Bank {
String getBankName();
}
代码语言:javascript复制package com.wangmengjun.tutorial.designpattern.abstractfactory;
public abstract class Loan {
protected double rate;
abstract void setCustomizeRate(double rate);
abstract void printLoanPayment(double amount, int year);
}
- 具体产品
银行类
代码语言:javascript复制package com.wangmengjun.tutorial.designpattern.abstractfactory;
public class ABCBank implements Bank {
@Override
public String getBankName() {
return "中国农业银行";
}
}
代码语言:javascript复制package com.wangmengjun.tutorial.designpattern.abstractfactory;
public class ICBCBank implements Bank{
@Override
public String getBankName() {
return "中国工商银行";
}
}
贷款类
代码语言:javascript复制package com.wangmengjun.tutorial.designpattern.abstractfactory;
public class HouseLoan extends Loan{
@Override
void printLoanPayment(double amount, int year) {
System.out.println("*****************住房贷款信息**************");
System.out.println("贷款金额:" amount);
System.out.println("贷款年数:" year);
System.out.println("贷款率:" rate);
}
@Override
void setCustomizeRate(double rate) {
this.rate = rate;
}
}
代码语言:javascript复制package com.wangmengjun.tutorial.designpattern.abstractfactory;
public class BusinessLoan extends Loan {
@Override
void printLoanPayment(double amount, int year) {
System.out.println("*****************商业贷款信息**************");
System.out.println("贷款金额:" amount);
System.out.println("贷款年数:" year);
System.out.println("贷款率:" rate);
}
@Override
void setCustomizeRate(double rate) {
this.rate = rate;
}
}
- 抽象工厂
package com.wangmengjun.tutorial.designpattern.abstractfactory;
public interface AbstractFactory<T> {
T create(String type) ;
}
这里为了以后每一种产品都适用,不去为每一种产品创建都指定一个方法,写了泛型,而没有写成如下的方式:
代码语言:javascript复制package com.wangmengjun.tutorial.designpattern.abstractfactory;
public interface AbstractFactory {
Bank createBank(String type) ;
Loan createLoan(String type);
}
- 具体工厂
package com.wangmengjun.tutorial.designpattern.abstractfactory;
public class BankFactory implements AbstractFactory<Bank>{
@Override
public Bank create(String type) {
if("icbc".equals(type) ) {
return new ICBCBank();
}else if("abc".equals(type)) {
return new ABCBank();
}
throw new IllegalArgumentException("Bank Type is illeagal");
}
}
代码语言:javascript复制package com.wangmengjun.tutorial.designpattern.abstractfactory;
public class LoanFactory implements AbstractFactory<Loan> {
@Override
public Loan create(String type) {
if("house".equals(type)) {
return new HouseLoan();
}else if("business".equals(type)) {
return new BusinessLoan();
}
throw new IllegalArgumentException("Loan type is ileagal");
}
}
用于获取抽象工厂实例的静态工厂方法类:
代码语言:javascript复制
package com.wangmengjun.tutorial.designpattern.abstractfactory;
public class FactoryProvider {
public static AbstractFactory<?> getFactory(String choice){
if("Bank".equalsIgnoreCase(choice)){
return new BankFactory();
}
else if("Loan".equalsIgnoreCase(choice)){
return new LoanFactory();
}
return null;
}
}
测试一下:
代码语言:javascript复制
package com.wangmengjun.tutorial.designpattern.abstractfactory;
public class Client {
public static void main(String[] args) {
AbstractFactory<?> bankFactory = FactoryProvider.getFactory("Bank");
Bank icbc =(Bank) bankFactory.create("icbc");
System.out.println(icbc.getBankName());
AbstractFactory<?> loanFactory = FactoryProvider.getFactory("Loan");
Loan houseLoan = (HouseLoan) loanFactory.create("house");
houseLoan.setCustomizeRate(5.14d);
houseLoan.printLoanPayment(1000000d, 20);
System.out.println();
System.out.println("*****************看看中国农业银行贷款信息*********************");
Bank abc =(Bank) bankFactory.create("abc");
System.out.println(abc.getBankName());
houseLoan = (HouseLoan) loanFactory.create("house");
houseLoan.setCustomizeRate(5.10d);
houseLoan.printLoanPayment(1000000d, 20);
Loan businessLoan = (BusinessLoan) loanFactory.create("business");
businessLoan.setCustomizeRate(6.14d);
businessLoan.printLoanPayment(1000000d, 10);
}
}
输出:
代码语言:javascript复制中国工商银行
*****************住房贷款信息**************
贷款金额:1000000.0
贷款年数:20
贷款率:5.14
*****************看看中国农业银行贷款信息*********************
中国农业银行
*****************住房贷款信息**************
贷款金额:1000000.0
贷款年数:20
贷款率:5.1
*****************商业贷款信息**************
贷款金额:1000000.0
贷款年数:10
贷款率:6.14
至此,一个银行贷款的相关的抽象工厂模式示例就完成了。
三. 抽象工厂模式的基本介绍
优缺点
优点
1、它分离了具体的类。Abstract Factory模式帮助你控制一个应用创建的对象的类。因为一个工厂封装创建产品对象的责任和过程,它将客户与类的实现分离。Client通过他们的抽象接口操纵实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户端代码中。
2、它有利于产品的一致性。当一个系列中的产品对象呗设计成一起工作时,一个应用一次只能使用同一个系列中的对象。这一点很重要。而Abstract Factory很容易实现这一点。
缺点
1、难以支持新种类的产品。难以扩展抽象工厂以生产新种类的产品。这是因为AbstarctProduct接口确定了可以被创建的产品集合。
参考
[1]. 阎宏. Java与模式.电子工业出版社
[2]. Erich Gamma. 设计模式-可复用面向对象软件的基础. 机械工业出版社.