问题:
当系统要创建一组相关或者相互依赖的对象时, 请使用抽象工厂模式.
抽象工厂模式可以向客户端提供一个接口, 使得客户端可以在不必指定产品的具体类型的情况下, 创建多个产品族中的产品对象. 这就是抽象工厂的用意.
类图:
源代码:
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.