1、介绍
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
简单工厂模式、工厂方法模式和抽象工厂模式区别
-
简单工厂:唯一工厂类,一个产品抽象类,工厂类的创建方法依据入参判断并创建具体产品对象。
-
工厂方法:多个工厂类,一个产品抽象类,利用多态创建不同的产品对象,避免了大量的if-else判断。
-
抽象工厂:多个工厂类,多个产品抽象类,产品子类分组,同一个工厂实现类创建同组中的不同产品,减少了工厂子类的数量。
2、主要作用
允许使用抽象的接口来创建一组相关产品,而不需要知道或关心实际生产出的具体产品是什么,这样就可以从具体产品中被解耦。
3、解决的问题
每个工厂只能创建一类产品
4、模式原理
(1)、UML类图
(2)、模式组成
抽象产品族(AbstractProduct) | 抽象产品的父类 | 描述抽象产品的公共接口 |
抽象产品(Product) | 具体产品的父类 | 描述具体产品的公共接口 |
具体产品(Concrete Product) | 抽象产品的子类;工厂类创建的目标类 | 描述生产的具体产品 |
抽象工厂(Creator) | 具体工厂的父类 | 描述具体工厂的公共接口 |
具体工厂(Concrete Creator) | 抽象工厂的子类;被外界调用 | 描述具体工厂;实现FactoryMethod工厂方法创建产品的实例 |
(3)、使用步骤
-
创建抽象工厂类,定义具体工厂的公共接口;
-
创建抽象产品族类,定义抽象产品的公共接口;
-
创建抽象产品类(继承抽象产品族类),定义具体产品的公共接口;
-
创建具体产品类(继承抽象产品类) & 定义生产的具体产品;
-
创建具体工厂类(继承抽象工厂类),定义创建对应具体产品实例的方法;
-
步骤6:**客户端通过实例化具体的工厂类,并调用其创建不同目标产品的方法创建不同具体产品类的实例
5、实例
a、有手机和路由器两种产品,有华为和小米两种品牌,两种品牌都可以生产手机和路由器
-
有手机和路由器两种产品,定义两个接口;
-
小米和华为都可以生产这两种产品,所以有4个实现类;
-
现在需要创建华为和小米的工厂类,先将工厂类进行抽象,里面有创建两个产品的方法,返回的是产品的接口类;
-
创建华为和小米的工厂实现类,继承工厂类接口,实现创建各自产品的方法;
-
客户端调用时,直接用工厂接口类创建需要的工厂,拿到对应的产品;
b、实例
步骤一:手机产品接口和路由器产品接口
//手机产品接口
public interface IPhoneProduct {
//开机
void start();
//关机
void shutdown();
//打电话
void callup();
//发邮件
void sendSMS();
}
//路由器产品接口
public interface IRouterProduct {
//开机
void start();
//关机
void shutdown();
//打开wifi
void openwifi();
//设置
void setting();
}
步骤二:华为和小米的产品的4个实现类
//华为手机实现类
public class HuaweiPhone implements IPhoneProduct {
@Override
public void start() {
System.out.println("开启华为手机");
}
@Override
public void shutdown() {
System.out.println("关闭华为手机");
}
@Override
public void callup() {
System.out.println("华为手机打电话");
}
@Override
public void sendSMS() {
System.out.println("华为手机发邮件");
}
}
//华为路由器实现类
public class HuaweiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("开启华为路由器");
}
@Override
public void shutdown() {
System.out.println("关闭华为路由器");
}
@Override
public void openwifi() {
System.out.println("打开华为wifi");
}
@Override
public void setting() {
System.out.println("设置华为路由器");
}
}
//小米手机实现类
public class XiaomiPhone implements IPhoneProduct {
@Override
public void start() {
System.out.println("开启小米手机");
}
@Override
public void shutdown() {
System.out.println("关闭小米手机");
}
@Override
public void callup() {
System.out.println("小米手机打电话");
}
@Override
public void sendSMS() {
System.out.println("小米手机发邮件");
}
}
//小米路由器实现类
public class XiaomiRouter implements IRouterProduct {
@Override
public void start() {
System.out.println("开启小米路由器");
}
@Override
public void shutdown() {
System.out.println("关闭小米路由器");
}
@Override
public void openwifi() {
System.out.println("打开小米wifi");
}
@Override
public void setting() {
System.out.println("设置小米路由器");
}
}
步骤三:工厂接口类
//产品工厂接口
public interface IProductFactory {
//生产手机
IPhoneProduct phoneProduct();
//生成路由器
IRouterProduct routerProduct();
}
步骤四:华为和小米工厂实现类,继承工厂接口
//华为工厂实现类
public class HuaweiFactory implements IProductFactory {
@Override
public IPhoneProduct phoneProduct() {
return new HuaweiPhone();
}
@Override
public IRouterProduct routerProduct() {
return new HuaweiRouter();
}
}
//小米工厂实现类
public class XiaomiFactory implements IProductFactory {
@Override
public IPhoneProduct phoneProduct() {
return new XiaomiPhone();
}
@Override
public IRouterProduct routerProduct() {
return new XiaomiRouter();
}
}
步骤五:客户端,通过 IProductFactory创建各自的工厂,通过工厂拿到对应的产品
public class Client {
public static void main(String[] args) {
System.out.println("============小米产品============");
//创建小米工厂
IProductFactory xiaomiFactory = new XiaomiFactory();
//生产小米手机
IPhoneProduct xiaomiPhone = xiaomiFactory.phoneProduct();
xiaomiPhone.start();
xiaomiPhone.sendSMS();
//生产小米路由器
IRouterProduct xiaomiRouter = xiaomiFactory.routerProduct();
xiaomiRouter.openwifi();
xiaomiRouter.setting();
System.out.println("============华为产品============");
//创建华为工厂
IProductFactory huaweiFactory = new HuaweiFactory();
//生产华为手机
IPhoneProduct huaweiPhone = huaweiFactory.phoneProduct();
huaweiPhone.start();
huaweiPhone.sendSMS();
//生产华为路由器
IRouterProduct huaweiRouter = huaweiFactory.routerProduct();
huaweiRouter.openwifi();
huaweiRouter.setting();
}
}
6、优点
(1)、降低耦合
抽象工厂模式将具体产品的创建延迟到具体工厂的子类中,这样将对象的创建封装起来,可以减少客户端与具体产品类之间的依赖,从而使系统耦合度低,这样更有利于后期的维护和扩展;
(2)、更符合开-闭原则
新增一种产品类时,只需要增加相应的具体产品类和相应的工厂子类即可
(3)、符合单一职责原则
每个具体工厂类只负责创建对应的产品
(4)、不使用静态工厂方法,可以形成基于继承的等级结构。
7、缺点
抽象工厂模式很难支持新种类产品的变化。
这是因为抽象工厂接口中已经确定了可以被创建的产品集合,如果需要添加新产品,此时就必须去修改抽象工厂的接口,这样就涉及到抽象工厂类的以及所有子类的改变,这样也就违背了“开发——封闭”原则。
8、应用场景
-
一个系统不要求依赖产品类实例如何被创建、组合和表达的表达,这点也是所有工厂模式应用的前提。
-
这个系统有多个系列产品,而系统中只消费其中某一系列产品