問題:
當系統要建立一組相關或者互相依賴的對象時, 請使用抽象工廠模式.
抽象工廠模式可以向用戶端提供一個接口, 使得用戶端可以在不必指定産品的具體類型的情況下, 建立多個産品族中的産品對象. 這就是抽象工廠的用意.
類圖:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZwpmL5J3b0NWYGR3YhJHdzJWQvwVdkNXZzlmcwJXdz9CX0Vmbf5GZzN2Xn9Gbi9CXzV2Zh1WavwFdl5mLuR2cj5yZvxmYvw1LcpDc0RHaiojIsJye.jpg)
源代碼:
package com.designpatterns.AbstractFactory;
/**
* 抽象工廠
*/
public interface AbstractFactory {
public AbstractProductA createProductA();
public AbstractProductB createProductB();
}
public interface AbstractProductA {
public void operation();
}
public interface AbstractProductB {
public void operation();
}
public class ConcreteFactory1 implements AbstractFactory{
public AbstractProductA createProductA(){
return new ProductA1();
}
public AbstractProductB createProductB(){
return new ProductB1();
}
}
public class ConcreteFactory2 implements AbstractFactory{
public AbstractProductA createProductA(){
return new ProductA2();
}
public AbstractProductB createProductB(){
return new ProductB2();
}
}
public class ProductA1 implements AbstractProductA {
public ProductA1(){
System.out.println("ProductA1...");
}
public void operation() {}
}
public class ProductA2 implements AbstractProductA {
public ProductA2(){
System.out.println("ProductA2...");
}
public void operation() {}
}
public class ProductB1 implements AbstractProductB {
public ProductB1(){
System.out.println("ProductB1...");
}
public void operation() {}
}
public class ProductB2 implements AbstractProductB {
public ProductB2(){
System.out.println("ProductB2...");
}
public void operation() {}
}
/**
* 用戶端類
*/
public class Client {
public static void main(String[] args) {
AbstractFactory af1 = new ConcreteFactory1();
af1.createProductA();
af1.createProductB();
AbstractFactory af2 = new ConcreteFactory2();
af2.createProductA();
af2.createProductB();
}
}
讨論:
AbstractFactory模式是為建立一組(有多類)相關或依賴的對象提供建立接口, 而Factory模式是為一類對象提供建立接口或延遲對象的建立到子類中實作. AbstractFactory模式通常都是使用Factory模式實作, 如上例所示.
Definition
Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
Class Diagram
Participants
- Abstract Factory (FinancialToolsFactory)
- declares an interface for operations that create abstract products objects
- Concrete Factory (EuropeFinancialToolsFactory, CanadaFinancialToolsFactory)
- implements the operations to create concrete product objects
- Abstract Product (TaxProcessor, ShipFeeProcessor)
- declares an interface for a type of product object
- Concrete Product (EuropeTaxProcessor, CanadaTaxProcessor, EuropeShipFeeProcessor, CanadaShipFeeProcessor)
- defines a product object to be created by the corresponding concrete factory implements the AbstractProduct interface
- Client (OrderProcessor)
- uses interfaces declared by AbstractFactory and AbstractProduct classes
Example: Financial Tools Factory
Example: Class Diagram
Example: Java sample code
// Factories
package com.apwebco.patterns.gof.abstractfactory;
public abstract class FinancialToolsFactory {
public abstract TaxProcessor createTaxProcessor();
public abstract ShipFeeProcessor createShipFeeProcessor();
}
public class CanadaFinancialToolsFactory extends FinancialToolsFactory {
public TaxProcessor createTaxProcessor() {
return new CanadaTaxProcessor();
}
public ShipFeeProcessor createShipFeeProcessor() {
return new CanadaShipFeeProcessor();
}
}
public class EuropeFinancialToolsFactory extends FinancialToolsFactory {
public TaxProcessor createTaxProcessor() {
return new EuropeTaxProcessor();
}
public ShipFeeProcessor createShipFeeProcessor() {
return new EuropeShipFeeProcessor();
}
}
// Products
public abstract class ShipFeeProcessor {
abstract void calculateShipFee(Order order);
}
public abstract class TaxProcessor {
abstract void calculateTaxes(Order order);
}
public class EuropeShipFeeProcessor extends ShipFeeProcessor {
public void calculateShipFee(Order order) {
// insert here Europe specific ship fee calculation
}
}
public class CanadaShipFeeProcessor extends ShipFeeProcessor {
public void calculateShipFee(Order order) {
// insert here Canada specific ship fee calculation
}
}
public class EuropeTaxProcessor extends TaxProcessor {
public void calculateTaxes(Order order) {
// insert here Europe specific taxt calculation
}
}
public class CanadaTaxProcessor extends TaxProcessor {
public void calculateTaxes(Order order) {
// insert here Canada specific taxt calculation
}
}
// Client
public class OrderProcessor {
private TaxProcessor taxProcessor;
private ShipFeeProcessor shipFeeProcessor;
public OrderProcessor(FinancialToolsFactory factory) {
taxProcessor = factory.createTaxProcessor();
shipFeeProcessor = factory.createShipFeeProcessor();
}
public void processOrder (Order order) {
// ....
taxProcessor.calculateTaxes(order);
shipFeeProcessor.calculateShipFee(order);
// ....
}
}
// Integration with the overall application
public class Application {
public static void main(String[] args) {
// .....
String countryCode = "EU";
Customer customer = new Customer();
Order order = new Order();
OrderProcessor orderProcessor = null;
FinancialToolsFactory factory = null;
if (countryCode == "EU") {
factory = new EuropeFinancialToolsFactory();
} else if (countryCode == "CA") {
factory = new CanadaFinancialToolsFactory();
}
orderProcessor = new OrderProcessor(factory);
orderProcessor.processOrder(order);
}
}
Benefits
- Isolates concrete classes
- Allows to change product family easily
- Promotes consistency among products
Usage
- When the system needs to be independent of how its products are created composed and represented.
- When the system needs to be configured with one of multiple families of products.
- When a family of products need to be used together and this constraint needs to be enforced.
- When you need to provide a library of products, expose their interfaces not the implementation.