抽象工厂模式浅析

2020-07-16 14:31:44 浏览数 (2)

一. 抽象工厂模式的基本介绍

意图

提供一个创建一系列或相互依赖对象的接口,而无需指定它们具体的类。

结构

抽象工厂模式的基本结构如下:

这里涉及到的参与者有如下几种:

  • 抽象工厂(AbstractFcatory)角色
    • 声明一个创建抽象产品对象的操作接口。
  • 具体工厂(ConcreteFactory)角色
    • 实现创建具体产品对象的操作。
  • 抽象产品(AbstractProduct)角色
    • 为一类产品对象声明一个接口
  • 具体产品(ConcreteProduct)角色
    • 定义一个将被相应的具体工厂创建的产品对象
    • 实现AbstractProduct接口
  • 抽象工厂(AbstractFcatory)角色
    • 仅使用由AbstractFactory和AbstractProduct类声明的接口

二. 抽象工厂模式的示例

接下来,我们创建两个产品族,一个是Bank,一个Loan,使用抽象工厂创建银行和贷款对象。

  • 抽象产品Bank和Loan
代码语言:javascript复制
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;

  }

}
  • 抽象工厂
代码语言:javascript复制
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);

}
  • 具体工厂

代码语言:javascript复制
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. 设计模式-可复用面向对象软件的基础. 机械工业出版社.

0 人点赞