定义:
为创建一组相关或依赖的对象提供一个接口,而无需指定它们的具体类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道具体的产品是什么。从而使客户从具体的产品中解耦,通用设计类图:
AbstractFactory接口提供了一组创建产品的方法,它的实现类ConcreteFactory1和ConcreteFactory2必须实现该方法来创建相关产品,不同的具体工厂类实现创建不同的产品家族的产品。要创建某一个产品,客户只需要使用其中的一个工厂类而不需要实例化任何具体的产品对象。AbstractProductA和AbstractProductB就是抽象的产品类,它们分别代表一个产品家族,实现类ProductA1和ProductA2是AbstractProductA产品家族的一组产品,实现类ProductB1和ProductB2是AbstractProductB产品家族的一组产品。
通用示例代码:
/**
* 抽象工厂
*/
public interface AbstractFactory {
/**创建A产品家族的产品*/
public AbstractProductA createProductA();
/**创建B产品家族的产品*/
public AbstractProductB createProductB();
}
public class ConcreteFactory1 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
//创建一个来自A产品家族的产品
return new ProductA1();
}
@Override
public AbstractProductB createProductB() {
//创建一个来自B产品家族的产品
return new ProductB1();
}
}
public class ConcreteFactory2 implements AbstractFactory {
@Override
public AbstractProductA createProductA() {
//创建一个来自A产品家族的产品
return new ProductA2();
}
@Override
public AbstractProductB createProductB() {
//创建一个来自B产品家族的产品
return new ProductB2();
}
}
/**
* 产品A家族
*/
public abstract class AbstractProductA {
/**每个产品共有的方法*/
public void shareMethod() {
}
/**每个产品不同实现的方法*/
public abstract void doSomething();
}
/**
* 产品B家族
*/
public abstract class AbstractProductB {
/**每个产品共有的方法*/
public void shareMethod() {
}
/**每个产品不同实现的方法*/
public abstract void doSomething();
}
public class ProductA1 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("产品A1的实现方法");
}
}
public class ProductA2 extends AbstractProductA {
@Override
public void doSomething() {
System.out.println("产品A2的实现方法");
}
}
public class ProductB1 extends AbstractProductB {
@Override
public void doSomething() {
System.out.println("产品B1的实现方法");
}
}
public class ProductB2 extends AbstractProductB {
@Override
public void doSomething() {
System.out.println("产品B2的实现方法");
}
}
public class Client {
public static void main(String[] args) {
//创建两个工厂
AbstractFactory factory1 = new ConcreteFactory1();
AbstractFactory factory2 = new ConcreteFactory2();
//使用factory1来创建一组产品,它们来自不同的产品家族
AbstractProductA productA1 = factory1.createProductA();
AbstractProductB productB1 = factory1.createProductB();
//使用factory2来创建一组产品,它们来自不同的产品家族
AbstractProductA productA2 = factory2.createProductA();
AbstractProductB productB2 = factory2.createProductB();
//do something...
}
}
客户端代码无需关心具体的产品对象,只通过创建工厂即可获得产品,客户端只需持有抽象工厂和抽象产品的引用即可后续操作。抽象工厂是工厂方法的升级,工厂方法是创建一种类型的产品,而抽象工厂重在生产一组相关的产品。
抽象工厂的优缺点
抽象工厂致力于解耦高层模块和低层模块,高层和低层模块都保持对抽象的依赖,是遵循依赖倒置原则的模范,同时也遵循迪米特法则,对客户端屏蔽了创建产品族的细节,但是也有缺点就是每增加一个新的产品家族,可能所有的工厂实现类都要修改,假如工厂类比较多,就会比较麻烦难以维护,但是即便如此,也阻挡不了使用它的优势,在产品族确定的情况下,可以扩展任意工厂类来实现新产品的创造。
举例
以超市中销售的饮料为例,我们知道现在超市中的饮料大致分为几大类如碳酸饮料、果汁饮料、凉茶饮料等,例如碳酸饮料有可口可乐、雪碧等,果汁饮料有汇源果汁、果粒橙等,凉茶饮料有加多宝、王老吉等,如果我们使用抽象工厂来生产超市所需的这几种饮料,那么每个工厂应该都能够生产碳酸饮料、果汁饮料的和凉茶饮料,用代码表示这个过程:
/**
* 抽象饮料类
*/
public abstract class Drink {
/**打印名称*/
abstract void printName();
/**打印售价*/
abstract void printPrice();
}
public abstract class CarbonatedDink extends Drink {
/**所有该类饮料共有的属性*/
public void commonProperty() {
System.out.println("碳酸饮料中都含有二氧化碳");
}
}
public abstract class JuiceDink extends Drink {
/**所有该类饮料共有的属性*/
public void commonProperty() {
System.out.println("果汁饮料中都含有果汁浓缩汁");
}
}
public abstract class CoolTeaDrink extends Drink {
/**所有该类饮料共有的属性*/
public void commonProperty() {
System.out.println("凉茶饮料中都含有中草药成分");
}
}
public class CocaCola extends CarbonatedDink {
@Override
void printName() {
System.out.println("可口可乐");
}
@Override
void printPrice() {
System.out.println("2.5元");
}
}
public class Sprite extends CarbonatedDink {
@Override
void printName() {
System.out.println("雪碧");
}
@Override
void printPrice() {
System.out.println("2.5元");
}
}
public class HuiYuanGuozhi extends JuiceDink {
@Override
void printName() {
System.out.println("汇源果汁");
}
@Override
void printPrice() {
System.out.println("2.0元");
}
}
public class GuoLiCheng extends JuiceDink {
@Override
void printName() {
System.out.println("果粒橙");
}
@Override
void printPrice() {
System.out.println("3.5元");
}
}
public class JiaDuoBao extends CoolTeaDrink {
@Override
void printName() {
System.out.println("加多宝凉茶");
}
@Override
void printPrice() {
System.out.println("3.5元");
}
}
public class WangLaoji extends CoolTeaDrink {
@Override
void printName() {
System.out.println("王老吉凉茶");
}
@Override
void printPrice() {
System.out.println("3.5元");
}
}
/**
* 生产饮料的抽象工厂
*/
public interface DrinkFactory {
/**创建碳酸饮料*/
CarbonatedDink createCarbonatedDink();
/**创建果汁饮料*/
JuiceDink createJuiceDink();
/**创建凉茶饮料*/
CoolTeaDrink createCoolTeaDrink();
}
public class DrinkFactory1 implements DrinkFactory {
@Override
public CarbonatedDink createCarbonatedDink() {
return new CocaCola();
}
@Override
public JuiceDink createJuiceDink() {
return new HuiYuanGuozhi();
}
@Override
public CoolTeaDrink createCoolTeaDrink() {
return new JiaDuoBao();
}
}
public class DrinkFactory2 implements DrinkFactory {
@Override
public CarbonatedDink createCarbonatedDink() {
return new Sprite();
}
@Override
public JuiceDink createJuiceDink() {
return new GuoLiCheng();
}
@Override
public CoolTeaDrink createCoolTeaDrink() {
return new WangLaoji();
}
}
public class Client {
public static void main(String[] args) {
//创建两个饮料工厂
DrinkFactory drinkFactory1 = new DrinkFactory1();
DrinkFactory drinkFactory2 = new DrinkFactory2();
System.out.println("drinkFactory1开始生产饮料>>>>>>>>>>>>");
//drinkFactory1创建一组饮料产品
CarbonatedDink cocaCola = drinkFactory1.createCarbonatedDink();
JuiceDink huiYuanGuozhi = drinkFactory1.createJuiceDink();
CoolTeaDrink jiaDuoBao = drinkFactory1.createCoolTeaDrink();
cocaCola.printName();
cocaCola.printPrice();
huiYuanGuozhi.printName();
huiYuanGuozhi.printPrice();
jiaDuoBao.printName();
jiaDuoBao.printPrice();
System.out.println("");
System.out.println("drinkFactory2开始生产饮料>>>>>>>>>>>>");
//drinkFactory2创建一组饮料产品
CarbonatedDink sprite = drinkFactory2.createCarbonatedDink();
JuiceDink guoLiCheng = drinkFactory2.createJuiceDink();
CoolTeaDrink wangLaoji = drinkFactory2.createCoolTeaDrink();
sprite.printName();
sprite.printPrice();
guoLiCheng.printName();
guoLiCheng.printPrice();
wangLaoji.printName();
wangLaoji.printPrice();
}
}
输出结果:
在什么情况下可以考虑使用抽象工厂模式
- 系统希望对外部屏蔽制造系列产品的细节过程,只输出结果。
- 系统中产品族的产品多于一个,而系统只消费其中某一产品族的产品。
- 属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
- 系统提供一个产品类的库,所有的产品以同样的接口出现,从而使客户端不依赖于实现。
参考: