目录
什么叫做抽象工厂模式
抽象工厂模式(Abstract Factory Pattern)是一种创建型设计模式,用于提供一个接口,使得客户端能够创建一系列相关或依赖的对象,而无需指定它们的具体类。这个模式有助于确保一组创建的对象能够协同工作,并且将对象的创建与使用相分离,使系统更加灵活、可维护和可扩展。
抽象工厂模式作用
抽象工厂模式(Abstract Factory Pattern)的主要作用是提供一种方式来创建一组相关或依赖的对象,同时保证这些对象之间的一致性和协同工作。
封装对象的创建过程:抽象工厂模式封装了对象的创建细节,客户端代码不需要知道具体对象是如何创建的,只需要通过抽象工厂接口来获取所需的对象。
实现产品族:抽象工厂模式可以用来创建一组相关的对象,这些对象通常属于同一个产品族(即一组相关或相互依赖的产品对象)。通过使用抽象工厂,可以确保这些相关对象的一致性和协同工作。
容易替换产品族:如果需要在应用程序中切换到不同的产品族(例如不同的外观主题、操作系统等),只需更改具体工厂的实现,而不需要修改客户端代码。增加了系统的灵活性。
降低耦合度:客户端代码与具体产品的实现相分离,因此更容易维护和扩展。如果需要添加新的产品或替换现有的产品,只需实现新的产品类和工厂。
提供一致的接口:抽象工厂模式要求具体工厂类提供一致的接口,这有助于确保客户端代码可以无缝地切换不同的工厂实现,而不会破坏应用程序的整体结构。
抽象工厂模式特征
抽象工厂接口(Abstract Factory Interface):定义了一组用于创建产品的抽象方法。通常,每个方法对应一个产品族,包括多个相关的产品。
具体工厂类(Concrete Factory Classes):实现抽象工厂接口,负责创建具体的产品对象。每个具体工厂类通常对应一个产品族。
抽象产品接口(Abstract Product Interface):定义了产品对象的抽象方法。每个产品族的产品都实现这个接口。
具体产品类(Concrete Product Classes):实现抽象产品接口,是具体产品的实际实现。
从特征来看,抽象工厂模式和工厂方法模式近乎一样,那么抽象工厂模式和我上一篇当中的工厂方法模式又有什么区别呢?
对比抽象工厂和工厂方法
相同点:
- 对象的创建封装:两者都封装了对象的创建过程,使客户端代码不需要了解具体对象的创建细节。
- 实现多态性:它们都通过使用抽象类或接口实现多态性,使得客户端可以通过通用的接口与具体的对象交互,而不需要关心具体对象的类型。
- 支持可扩展性:两者都支持可扩展性,可以轻松地添加新的产品类或工厂类,而不需要修改现有的代码。
不同点:
- 数量和复杂度:
- 抽象工厂模式通常涉及多个抽象工厂、多个具体工厂、多个抽象产品接口和多个具体产品类。它适用于创建多个不同类型的产品对象。
- 工厂方法模式通常涉及一个抽象工厂接口、多个具体工厂类、一个抽象产品接口和多个具体产品类。它适用于创建单一类型的产品对象。
- 关注点不同:
- 抽象工厂模式关注于创建整个产品族,客户端通常需要使用一组相关的产品对象。
- 工厂方法模式关注于创建单个产品,客户端只需要一个特定类型的产品对象。
抽象工厂模应用场景
需要创建一组相关的产品对象:当您的应用程序需要同时创建多个相关的对象,这些对象通常一起使用,并且具有一定的关联性,抽象工厂模式可以帮助您管理这些对象的创建。
产品对象存在一定的族群关系:如果您的产品对象可以分为不同的族群,每个族群都有一组相关的产品,例如不同操作系统下的界面元素、不同风格的家具等,抽象工厂模式是一个有用的设计模式。
需要确保产品一致性:抽象工厂模式可以确保创建的产品对象都满足一组共同的接口或抽象类,这有助于确保这些产品对象可以一致地协同工作。
需要支持多个产品族:如果您的应用程序需要支持多个不同的产品族,并且这些产品族之间的切换要求是相对频繁的,抽象工厂模式可以提供一种灵活的方式来支持这种切换。
跨平台开发:在跨多个平台的应用程序中,抽象工厂模式可以用于创建适应不同平台的对象,以确保应用程序在不同平台上能够正确运行。
抽象工厂模式的实现
以下是一个简单的抽象工厂模式的实现示例,以创建不同类型的形状(矩形和圆形)和颜色(红色和蓝色)为例:
定义抽象工厂接口
- 定义了抽象产品的通用行为,包括Shape和Color接口。
- 接口表示了不同产品类的抽象,客户端代码可以通过这些接口来与具体产品对象交互。
// 抽象产品接口 - 形状
interface Shape {
void draw();
}
// 抽象产品接口 - 颜色
interface Color {
void fill();
}
实现具体产品类
- 在此步骤中,我们实现了具体产品的不同版本,包括Rectangle、Circle、Red 和 Blue类。
- 这些具体产品类分别表示了不同形状和颜色的产品,它们实现了相应的抽象产品接口。
// 具体产品类 - 矩形
class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
// 具体产品类 - 圆形
class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
// 具体产品类 - 红色
class Red implements Color {
@Override
public void fill() {
System.out.println("填充红色");
}
}
// 具体产品类 - 蓝色
class Blue implements Color {
@Override
public void fill() {
System.out.println("填充蓝色");
}
}
定义抽象工厂接口
- 此步骤定义了抽象工厂的接口,包括AbstractFactor接口。
- 抽象工厂接口中声明了用于创建产品的抽象方法,这些方法返回抽象产品的引用。
// 抽象工厂接口
interface AbstractFactory {
Shape createShape();
Color createColor();
}
实现具体工厂类
- 在这一步中,我们实现了具体工厂类ShapeFactory和ColorFactory。
- 具体工厂类分别实现了抽象工厂接口中的方法,用于创建特定类型的产品。
- 每个具体工厂类负责创建一组相关的产品对象(矩形和红色、圆形和蓝色)。
// 具体工厂类 - 形状工厂
class ShapeFactory implements AbstractFactory {
@Override
public Shape createShape() {
return new Rectangle(); // 可以根据需要返回不同的具体形状对象
}
@Override
public Color createColor() {
return new Red(); // 可以根据需要返回不同的具体颜色对象
}
}
// 具体工厂类 - 颜色工厂
class ColorFactory implements AbstractFactory {
@Override
public Shape createShape() {
return new Circle(); // 可以根据需要返回不同的具体形状对象
}
@Override
public Color createColor() {
return new Blue(); // 可以根据需要返回不同的具体颜色对象
}
}
进行测试
- 在客户端代码中,我们创建了Main类,其中包含了createShapesAndColors方法,该方法接受一个抽象工厂作为参数。
- 客户端代码可以根据需要选择不同的工厂(形状工厂或颜色工厂)来创建产品对象。
- 使用抽象工厂模式,客户端代码可以创建一组相关的产品对象,而不需要了解具体产品的实现细节。
public class Main {
public static void createShapesAndColors(AbstractFactory factory) {
Shape shape = factory.createShape();
Color color = factory.createColor();
shape.draw();
color.fill();
}
public static void main(String[] args) {
// 使用形状工厂
System.out.println("使用形状工厂:");
AbstractFactory shapeFactory = new ShapeFactory();
createShapesAndColors(shapeFactory);
// 使用颜色工厂
System.out.println("\n使用颜色工厂:");
AbstractFactory colorFactory = new ColorFactory();
createShapesAndColors(colorFactory);
}
}
测试结果:
总结
抽象工厂模式的优点:
- 产品一致性:确保创建的产品对象都满足一组共同的接口,创建的对象在整个系统中保持一致性,属于同一产品族。
- 解耦合:客户端代码与具体产品的实现分离,容易维护和扩展。
- 多态性:支持处理不同类型的产品,提高系统灵活性。
- 支持开闭原则:可以轻松添加新的产品族,不影响现有代码。
抽象工厂模式的缺点:
- 复杂性:引入多个抽象类和接口,可能增加系统复杂性。
- 不易扩展产品种类:添加新的产品种类需要修改抽象工厂接口和所有具体工厂类。
- 不适用于单一产品情景:适用于创建一组相关的产品,不适用于单一产品。
- 运行时切换困难:切换不同的产品族通常需要修改客户端代码,可能增加复杂性。