设计模式总的来说分为3类:创建型模式(5种)、结构型模式(7种)、行为型模式(11种),其中创建型模式分为:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式,这里要总结的就是创建型模式中的抽象工厂模式。
准备工作:
总结抽象工厂模式之前,先介绍两个概念:产品族和产品等级结构(参考图片)。
产品等级结构:源自同一抽象产品角色的不同具体产品位于同一产品等级。例如抽象产品角色为冰箱接口,其子类有海尔冰箱和格力冰箱,海尔冰箱和格力冰箱它们是位于同一产品等级的,同理,海尔空调和格力空调也是位于同一产品等级。
产品族:同一工厂生产的,并处在不同产品等级结构中相同位置的产品构成一个产品族。例如有两个工厂,一个是海尔电器工厂,一个是格力电器工厂。其中海尔电器工厂生产海尔冰箱和海尔空调,海尔冰箱和海尔空调一个是位于冰箱产品等级结构中,一个是位于空调的等级结构中,虽然产品等级结构不同,但是位置却相同,故海尔冰箱和海尔空调构成一个产品族;格力冰箱和格力空调构成一个产品族。
抽象工厂模式:
为什么要使用抽象工厂模式?有了产品等级结构和产品族的概念,可以熟知工厂方法模式针对的都是同一产品等级结构,一个工厂只能生产一种产品,当一个工厂想要生产多个产品的时候(一个产品族),就需要使用到抽象工厂模式了。通俗的解释一下,在工厂方法模式中,假设有两个工厂,一个工厂生产冰箱,一个工厂生产空调,由于成本和人力的不断提高,厂方决定引入新技术,缩减成本和人力,将两个工厂干的事情合并到一个工厂。但是有个前提条件,产品必须是位于不同产品等级的,不能一个工厂即生产海尔的冰箱由生产格力冰箱,这显然是不符合逻辑的,会遭格力举报的。
有了上面的铺垫,现在来看看抽象工厂模式中各个角色和其职责:
抽象工厂角色: | 抽象工厂模式中的核心,它是一个抽象类或接口,所有具体工厂都要继承或实现它。 |
具体工厂角色: | 具体工厂,负责产品的创建,即生成具体的对象。 |
抽象产品角色: | 工厂所创建实例的父类,所有产品都要实现该接口,或继承该抽象类。 |
具体产品角色: | 具体的产品类,工厂的目的就是要创建这些产品类的实例。 |
抽象工厂模式的例子,使用海尔和格力产品的创建来说明。首先来创建两个抽象产品角色:
/**
* 抽象产品角色:冰箱接口
*/
public interface FridgeInterface {
void function();
}
/**
* 抽象产品角色:空调接口
*/
public interface AirConditionInterface {
void functoin();
}
创建具体的产品角色,海尔冰箱和海尔空调
/**
* 具体产品角色:海尔冰箱
*/
public class HaierFridge implements FridgeInterface {
public HaierFridge() {
System.out.println("生产海尔冰箱");
}
@Override
public void function() {
System.out.println("海尔冰箱可以冰冻啤酒");
}
}
/**
* 具体产品角色:海尔空调
*/
public class HaierAirCondition implements AirConditionInterface {
public HaierAirCondition() {
System.out.println("生产海尔空调");
}
@Override
public void functoin() {
System.out.println("海尔空调可以调节室内温度");
}
}
创建抽象工厂:
/**
* 抽象工厂角色:工厂创建的产品是一个产品族,但不是一个产品等级结构
*/
public interface HaierFactory {
HaierFridge getHaierFridge();
HaierAirCondition getHaierAirCondition();
}
接着创建一个工厂,该工厂既可以生产冰箱,又可以生产空调。
/**
* 具体工厂角色
*/
public class HaierFactoryImpl implements HaierFactory{
@Override
public HaierFridge getHaierFridge() {
return new HaierFridge();
}
@Override
public HaierAirCondition getHaierAirCondition() {
return new HaierAirCondition();
}
}
客户端:
/**
* 客户端
*/
public class Client {
public static void main(String[] args) {
HaierFactory factory= new HaierFactoryImpl();
factory.getHaierFridge();
factory.getHaierAirCondition();
}
}
控制台打印:
生产海尔冰箱
生产海尔空调
优缺点分析:
优点:隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易。增加新的具体工厂和产品族很方便,无须修改已有系统,符合“开闭原则”。
缺点:在添加新的产品对象时,难以扩展抽象工厂来生产新种类的产品,这是因为在抽象工厂角色中规定了所有可能被创建的产品集合,要支持新种类的产品就意味着要对该接口进行扩展,而这将涉及到对抽象工厂角色及其所有子类的修改,显然会带来较大的不便。开闭原则的倾斜性(增加新的工厂和产品族容易,增加新的产品等级结构麻烦)
。
参考文章:https://www.kancloud.cn/digest/xing-designpattern/143724