在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。我们可以想一下,有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象,即产品族。
这个时候我们就需要使用抽象工厂模式。
在讲解抽象工厂模式之前,我们需要介绍两个概念:
提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
遵循的原则:
未遵循的原则:
抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来。而工厂模式只是用于创建一个对象,这和抽象工厂模式有很大不同。
抽象工厂模式用到了工厂模式来创建单一对象,在类图左部,AbstractFactory 中的 CreateProductA 和 CreateProductB 方法都是让子类来实现,这两个方法单独来看就是在创建一个对象,这符合工厂模式的定义。
至于创建对象的家族这一概念是在 Client 体现,Client 要通过 AbstractFactory 同时调用两个方法来创建出两个对象,在这里这两个对象就有很大的相关性,Client 需要同时创建出这两个对象。
从高层次来看,抽象工厂使用了组合,即 Cilent 组合了 AbstractFactory,而工厂模式使用了继承。
问题描述:
依然是披萨店。为了要保证每家加盟店都能够生产高质量的披萨,防止使用劣质的原料,我们打算建造一家生产原料的工厂,并将原料运送到各家加盟店。但是加盟店都位于不同的区域,比如纽约、芝加哥。纽约使用一组原料,芝加哥使用另一种原料。在这里我们可以这样理解,这些不同的区域组成了原料家族,每个区域实现了一个完整的原料家族。
首先定义原料接口-酱汁和面团
package com.wpx.abstractfactory;
/**
* 原料接口-酱汁
*/
public interface Sauce {
public String sauceType();
}
package com.wpx.abstractfactory;
/**
* 原料接口-面团
*/
public interface Dough {
public String doughType();
}
再定义具体的原料类-李子番茄酱、纯番茄酱、薄壳面团、厚壳面团
package com.wpx.abstractfactory;
/**
* 具体原料-李子番茄酱
*/
public class PlumTomatoSauce implements Sauce {
@Override
public String sauceType() {
return "李子番茄酱";
}
}
package com.wpx.abstractfactory;
/**
* 具体原料-纯番茄酱
*/
public class MarinaraSauce implements Sauce {
@Override
public String sauceType() {
return "纯番茄酱";
}
}
package com.wpx.abstractfactory;
/**
* 薄壳面团
*/
public class ThinCrustDough implements Dough {
@Override
public String doughType() {
return "薄壳面团";
}
}
package com.wpx.abstractfactory;
/**
* 厚壳面团
*/
public class ThickCrustDough implements Dough {
@Override
public String doughType() {
return "厚壳面团";
}
}
有了原料,现在我们来定义一个抽象工厂接口-披萨原料工厂
package com.wpx.abstractfactory;
/**
* 抽象工厂-披萨原料工厂
*/
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
}
紧接着,我们来找两个加盟商(具体工厂),纽约原料工厂和芝加哥原料工厂
package com.wpx.abstractfactory;
/**
* 具体原料工厂-纽约原料工厂
*/
public class NYPizzaIngredientFactory implements PizzaIngredientFactory{
@Override
public Dough createDough() {
return new ThickCrustDough();
}
@Override
public Sauce createSauce() {
return new MarinaraSauce();
}
}
package com.wpx.abstractfactory;
/**
* 具体原料工厂-芝加哥原料工厂
*/
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory{
@Override
public Dough createDough() {
return new ThinCrustDough();
}
@Override
public Sauce createSauce() {
return new PlumTomatoSauce();
}
}
现在该有一个披萨店去制作披萨
package com.wpx.abstractfactory;
/**
* 纽约披萨店
*/
public class NYPizzaStore {
private PizzaIngredientFactory ingredientFactory;
public NYPizzaStore() {
// 纽约店会用到纽约披萨原料工厂,由该原料工厂负责生产使用纽约风味披萨所需的原料
ingredientFactory = new NYPizzaIngredientFactory();
}
public void makePizza() {
Dough dough = ingredientFactory.createDough();
Sauce sauce = ingredientFactory.createSauce();
System.out.println(dough.doughType());
System.out.println(sauce.sauceType());
}
}
现在我们去纽约的披萨店整一份披萨尝尝
package com.wpx.abstractfactory;
/**
* 测试抽象工厂模式
*/
public class NYPizzaStoreDemo {
public static void main(String[] args) {
NYPizzaStore nyPizzaStore = new NYPizzaStore();
nyPizzaStore.makePizza();
}
}
运行结果
厚壳面团
纯番茄酱
Process finished with exit code 0
java.util.Calendar#getInstance()
java.util.Arrays#asList()
java.util.ResourceBundle#getBundle()
java.sql.DriverManager#getConnection()
java.sql.Connection#createStatement()
java.sql.Statement#executeQuery()
java.text.NumberFormat#getInstance()
javax.xml.transform.TransformerFactory#newInstance()
优点:
缺点:
使用场景