目录
什么是抽象工厂模式
抽象工厂模式的实现
工厂方法模式角色
抽象工厂模式类图
抽象工厂模式代码实现
抽象工厂模式的特点
优点
缺点
使用场景
注意事项
实际应用
什么是抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)隶属于设计模式中的创建型模式,用于产品族的构建。抽象工厂是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂是指当有多个抽象角色时使用的一种工厂模式。抽象工厂模式可以向客户端提供一个接口,使客户端在不必指定产品的具体情况下,创建多个产品族中的产品对象。
在介绍抽象工厂模式前,我们先厘清两个概念:
产品等级结构:产品等级结构指的是产品的继承结构,例如一个汽车抽象类,它有蔚来汽车、特斯拉汽车、比亚迪汽车等一系列的子类,那么这个汽车抽象类和他的子类就构成了一个产品等级结构。产品族:产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。比如,比亚迪工厂生产唐、宋,那么唐、宋则位于空调产品族中。
抽象工厂模式主要用于创建相关对象的家族。当一个产品族中需要被设计在一起工作时,通过抽象工厂模式,能够保证客户端始终只使用同一个产品族中的对象;并且通过隔离具体类的生成,使得客户端不需要明确指定具体生成类;所有的具体工厂都实现了抽象工厂中定义的公共接口,因此只需要改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。
但该模式的缺点在于添加新的行为时比较麻烦,如果需要添加一个新产品族对象时,需要更改接口及其下所有子类,这必然会带来很大的麻烦。
抽象工厂模式的实现
工厂方法模式角色
- 抽象工厂角色(Abstract Factory):描述具体工厂的公共接口,是具体工厂的父类。
- 具体工厂角色(Concrete Factory):描述具体工厂,创建产品的实例,供外界调用,主要实现了抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品角色(Product):抽象产品角色是简单工厂模式所创建的所有对象的父类,负责描述所有实例所共有的公共接口,它的引入将提高系统的灵活性,使得在工厂类中只需定义一个工厂方法,因为所有创建的具体产品对象都是其子类对象。
- 具体产品角色(Concrete Product)具体产品角色是简单工厂模式的创建目标,所有创建的对象都充当这个角色的某个具体类的实例。每一个具体产品角色都继承了抽象产品角色,需要实现定义在抽象产品中的抽象方法,由具体工厂来创建,它同具体工厂之间一一对应。
抽象工厂模式类图
抽象工厂模式代码实现
抽象产品角色
/** * @author Evan Walker * @version 1.0 * @desc 昂焱数据: https://www.ayshuju.com * @date 2023/04/04 13:41:41 */ public interface Color { String getColor(); } public interface Taste { String getTaste(); }具体产品角色
* @author Evan Walker * @version 1.0 * @desc 昂焱数据: https://www.ayshuju.com * @date 2023/04/04 13:42:21 */ public class Apple implements Color { @Override public String getColor() { return "红色"; } } public class Orange implements Color { @Override public String getColor() { return "橙色"; } } public class Pear implements Color { @Override public String getColor() { return "黄色"; } } public class Coke implements Taste { @Override public String getTaste() { return "好喝打嗝"; } } public class Milk implements Taste { @Override public String getTaste() { return "香"; } } public class Wine implements Taste { @Override public String getTaste() { return "好喝上头"; } }抽象工厂角色
/** * @author Evan Walker * @version 1.0 * @desc 昂焱数据: https://www.ayshuju.com * @date 2023/04/06 13:58:37 */ public abstract class AbstractFactory { public abstract Color getColor(String name); public abstract Taste getTaste(String name); }具体工厂角色
/** * @author Evan Walker * @version 1.0 * @desc 昂焱数据: https://www.ayshuju.com * @date 2023/04/06 14:44:44 */ public class ColorFactory extends AbstractFactory { @Override public Color getColor(String name) { if(name == null){ return null; } if(name.equalsIgnoreCase("APPLE")){ return new Apple(); } else if(name.equalsIgnoreCase("ORANGE")){ return new Orange(); } else if(name.equalsIgnoreCase("PEAR")){ return new Pear(); } return null; } @Override public Taste getTaste(String taste) { return null; } } public class TasteFactory extends AbstractFactory { @Override public Color getColor(String name) { return null; } @Override public Taste getTaste(String name) { if(name == null){ return null; } if(name.equalsIgnoreCase("MILK")){ return new Milk(); } else if(name.equalsIgnoreCase("WINE")){ return new Wine(); } else if(name.equalsIgnoreCase("COKE")){ return new Coke(); } return null; } }创建一个工厂创造器/生成器类,通过传递形状或颜色信息来获取工厂,并进行测试。
/** * @author Evan Walker * @version 1.0 * @desc 昂焱数据: https://www.ayshuju.com * @date 2023/04/06 15:45:51 */ public class FactoryProducer { public static AbstractFactory getFactory(String choice){ if(choice.equalsIgnoreCase("TASTE")){ return new TasteFactory(); } else if(choice.equalsIgnoreCase("COLOR")){ return new ColorFactory(); } return null; } }/** * @author Evan Walker * @version 1.0 * @desc * @date 2023/04/04 14:02:43 */ public class Test { public static void main(String[] args) { //获取味道工厂 AbstractFactory tasteFactory = FactoryProducer.getFactory("Taste"); Taste taste = tasteFactory.getTaste("Wine"); System.out.println(taste.getTaste()); taste= tasteFactory.getTaste("milk"); System.out.println(taste.getTaste()); taste= tasteFactory.getTaste("COKE"); System.out.println(taste.getTaste()); //获取颜色工厂 AbstractFactory colorFactory = FactoryProducer.getFactory("Color"); Color color = colorFactory.getColor("apple"); color.getColor(); System.out.println(color.getColor()); color = colorFactory.getColor("orange"); System.out.println(color.getColor()); color = colorFactory.getColor("pear"); System.out.println(color.getColor()); } }抽象工厂模式的特点
优点
- 提供了一种封装对象创建过程的方式:抽象工厂模式将对象的创建过程封装在了具体的工厂类中,客户端只需要关注工厂接口和产品接口,无需关心具体的实现细节。
- 实现了产品族的切换:通过使用不同的具体工厂类,可以方便地切换整个产品族的产品,从而实现了接口与实现的分离。
- 保持了代码的一致性:抽象工厂模式保持了一致性,即所有由同一工厂创建的产品都相互关联,使得产品之间可以很方便地进行配合使用。
缺点
- 不易扩展新的产品:当需要给产品家族新增一个产品时,需要修改抽象工厂的接口及所有的具体工厂类,这就违反了开闭原则,增加了代码的维护成本。
- 增加了系统的复杂度:抽象工厂模式引入了多个抽象和具体类,增加了系统的复杂度和理解难度。
使用场景
- 必须创建一系列相互关联或相互依赖的产品对象。
- 需要提供一个统一的接口,将客户端与具体实现解耦。
- 需要在运行时切换不同的产品族。
注意事项
- 注意抽象工厂接口的设计,应该根据业务需求合理定义所需方法。
- 了解产品族和产品等级结构之间的关系,避免设计出不符合实际需求的工厂类结构。
实际应用
- GUI工具包:不同的操作系统(如Windows、Linux)提供了不同的GUI工具包,抽象工厂模式可以用于创建具体的按钮、文本框等GUI组件。
- 数据库访问:数据库访问框架可以根据配置文件或运行时参数选择不同的数据库访问驱动,抽象工厂模式可以用于创建不同类型的数据库连接和操作对象。
- 游戏开发:在游戏开发中,可以使用抽象工厂模式来创建不同种类的角色、武器、装备等物品。