设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。用工厂方式代替new操作的一种模式。
目录
前言
设计模式是一套被反复使用、多数人认可的、经过分类编目的、代码设计经验的总结。它们为软件设计提供了一定的指导和最佳实践。特别是在创建对象时,简单工厂、工厂模式和抽象工厂模式这三种创建型模式经常被提及和应用。
一、简单工厂模式(Simple Factory)
1.什么是简单工厂模式
简单工厂模式是一种创建型设计模式,它通过一个单一的工厂类来负责创建一系列相关的对象。这个工厂类根据传入的参数来决定实例化哪一个具体类的实例。客户端在使用时不需要知道具体的类名,只需要提供必要的信息给工厂。
2.简单工厂的核心角色
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品(Concrete Product):实现或继承抽象产品接口的类。每一种产品都有各自的特点。
- 简单工厂(Simple Factory):根据传入的参数来决定创建哪一个具体类的实例。
3.具体实现
1)抽象产品
代码如下(示例):
// 抽象产品
interface Product {
void show();
}
2)具体产品
代码如下(示例):
// 具体产品A
class ConcreteProductA implements Product {
public void show() {
System.out.println("This is product A.");
}
}
// 具体产品B
class ConcreteProductB implements Product {
public void show() {
System.out.println("This is product B.");
}
}
3)简单工厂
代码如下(示例):
// 简单工厂
class SimpleFactory {
public static Product createProduct(String type) {
if (type == null) {
return null;
}
if (type.equalsIgnoreCase("A")) {
return new ConcreteProductA();
} else if (type.equalsIgnoreCase("B")) {
return new ConcreteProductB();
}
return null;
}
}
4)客户端调用
代码如下(示例):
// 客户端调用
public class Client {
public static void main(String[] args) {
Product productA = SimpleFactory.createProduct("A");
productA.show(); // 输出 "This is product A."
Product productB = SimpleFactory.createProduct("B");
productB.show(); // 输出 "This is product B."
}
}
在这个例子中,我们定义了一个抽象产品接口Product
和两个具体产品类ConcreteProductA
和ConcreteProductB
。然后,我们创建了一个简单的工厂类SimpleFactory
,它根据传入的类型参数来创建相应的具体产品实例。最后,在客户端代码中,我们使用简单工厂来创建并显示不同类型的产品。
4.简单工厂的适用性
-
当对象的创建过程相对集中,并且客户端对于如何创建对象不感兴趣时,简单工厂可以封装这些创建细节。
-
如果产品的种类相对较少,并且不太可能发生变化,简单工厂可以减少系统的复杂性。
-
当希望避免客户端代码直接实例化对象,而是通过一个统一的接口来创建对象时,简单工厂可以提供这样的接口。
-
简单工厂更适合那些创建逻辑比较简单的情况,如果创建过程涉及复杂的逻辑判断或者条件分支,可能需要考虑其他工厂模式,如工厂方法或抽象工厂。
-
当客户端代码不依赖于产品的具体类,而只需要知道产品的接口或抽象类时,简单工厂可以帮助客户端与具体类解耦。
二、工厂模式(Factory Method)
1.什么是工厂模式
工厂模式属于创建型模式,它在创建对象时提供了一种封装机制,将实际创建对象的代码与使用代码分离。定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
2.工厂模式的核心角色
- 抽象产品(Product):定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品(Concrete Product):实现或继承抽象产品接口的类。每一种产品都有各自的特点。
- 抽象工厂(Factory):声明了创建抽象产品的接口,但由它的子类来确定要实例化的具体产品类。
- 具体工厂(Concrete Factory):实现抽象工厂接口,并返回一个等级结构中的具体产品实例。
3.具体实现
1)抽象产品
代码如下(示例):
// 抽象产品
interface Animal {
void speak();
}
2)具体产品
代码如下(示例):
// 具体产品A
class Dog implements Animal {
public void speak() {
System.out.println("汪汪汪!");
}
}
// 具体产品B
class Cat implements Animal {
public void speak() {
System.out.println("喵喵喵!");
}
}
3)抽象工厂
代码如下(示例):
// 工厂接口
interface AnimalFactory {
Animal createAnimal();
}
4)具体工厂
代码如下(示例):
/ 具体工厂A
class DogFactory implements AnimalFactory {
public Animal createAnimal() {
return new Dog();
}
}
// 具体工厂B
class CatFactory implements AnimalFactory {
public Animal createAnimal() {
return new Cat();
}
}
4)客户端调用
代码如下(示例):
// 客户端调用
public class Client {
public static void main(String[] args) {
AnimalFactory dogFactory = new DogFactory();
Animal dog = dogFactory.createAnimal();
dog.speak(); // 输出 "汪汪汪!"
AnimalFactory catFactory = new CatFactory();
Animal cat = catFactory.createAnimal();
cat.speak(); // 输出 "喵喵喵!"
}
}
在这个例子中,我们定义了一个抽象产品接口Animal
和两个具体产品类Dog
和Cat
。然后,我们创建了一个工厂接口AnimalFactory
和两个具体工厂类DogFactory
和CatFactory
,它们分别负责创建具体的动物实例。最后,在客户端代码中,我们使用不同的工厂来创建并显示不同类型的动物。
4.工厂模式的适用性
-
如果一个对象的创建过程需要多个步骤,或者涉及到复杂的逻辑判断和条件分支,那么使用工厂模式可以将这些复杂性封装在工厂类中,客户端只需要调用工厂类的接口即可获取所需的对象。
-
工厂模式通过将对象的创建和使用分离,降低了客户端和具体类之间的耦合度。客户端不需要知道具体的类名,只需要知道工厂类的接口,这有助于提高代码的可维护性和扩展性。
-
工厂模式提供了一个创建对象的接口,使得客户端可以根据需要动态地创建对象。这种灵活性在很多应用场景中非常有用。
-
工厂模式可以在真正需要对象的时候才创建它,而不是在程序启动时就创建所有的对象。这有助于减少系统的内存占用和启动时间。
-
工厂模式遵循了面向对象设计中的开闭原则,即对扩展开放,对修改封闭。当需要添加新的产品类型时,只需添加新的具体工厂类和具体产品类,无需修改现有的代码。
三、抽象工厂模式(Abstract Factory)
1.什么是抽象工厂模式
抽象工厂模式提供了一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。它是一种比简单工厂和工厂方法更高层次的设计模式。它围绕一个超级工厂创建其他工厂,该超级工厂又称为其他工厂的工厂。提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。通过使用抽象工厂模式,可以将客户端与具体产品的创建过程解耦,使得客户端可以通过工厂接口来创建一族产品。
2.抽象工厂的核心角色
- 抽象产品(Abstract Product):定义了产品的规范,描述了产品的主要特性和功能。
- 具体产品(Concrete Product):实现或继承抽象产品接口的类。每一种产品都有各自的特点。
- 抽象工厂(Abstract Factory):声明了创建抽象产品的接口,由子类确定要生成的具体产品类。
- 具体工厂(Concrete Factory):实现抽象工厂接口,并返回一系列具体产品的实例。
3.具体实现
1)抽象产品
代码如下(示例):
// 抽象产品A
interface ProductA {
void show();
}
// 抽象产品B
interface ProductB {
void show();
}
2)具体产品
代码如下(示例):
// 具体产品A1
class ConcreteProductA1 implements ProductA {
public void show() {
System.out.println("This is product A1.");
}
}
// 具体产品A2
class ConcreteProductA2 implements ProductA {
public void show() {
System.out.println("This is product A2.");
}
}
// 具体产品B1
class ConcreteProductB1 implements ProductB {
public void show() {
System.out.println("This is product B1.");
}
}
// 具体产品B2
class ConcreteProductB2 implements ProductB {
public void show() {
System.out.println("This is product B2.");
}
}
3)抽象工厂
代码如下(示例):
// 抽象工厂
interface AbstractFactory {
ProductA createProductA();
ProductB createProductB();
}
4)具体工厂
代码如下(示例):
// 具体工厂A
class ConcreteFactoryA implements AbstractFactory {
public ProductA createProductA() {
return new ConcreteProductA1();
}
public ProductB createProductB() {
return new ConcreteProductB1();
}
}
// 具体工厂B
class ConcreteFactoryB implements AbstractFactory {
public ProductA createProductA() {
return new ConcreteProductA2();
}
public ProductB createProductB() {
return new ConcreteProductB2();
}
}
4)客户端调用
代码如下(示例):
public class Client {
public static void main(String[] args) {
AbstractFactory factoryA = new ConcreteFactoryA();
ProductA productA1 = factoryA.createProductA();
productA1.show(); // 输出 "This is product A1."
ProductB productB1 = factoryA.createProductB();
productB1.show(); // 输出 "This is product B1."
AbstractFactory factoryB = new ConcreteFactoryB();
ProductA productA2 = factoryB.createProductA();
productA2.show(); // 输出 "This is product A2."
ProductB productB2 = factoryB.createProductB();
productB2.show(); // 输出 "This is product B2."
}
}
在这个例子中,我们定义了两个抽象产品接口ProductA
和ProductB
,以及它们各自的具体产品类。然后,我们创建了一个抽象工厂接口AbstractFactory
和两个具体工厂类ConcreteFactoryA
和ConcreteFactoryB
,它们分别负责创建具体的产品实例。最后,在客户端代码中,我们使用不同的工厂来创建并显示不同类型的产品。
4.抽象工厂的适用性
- 当需要强调一系列相关的产品对象时,这些产品对象通常是同一个产品族的一部分,并且经常一起使用。例如,一个软件包可能包含多个组件,如编辑器、编译器和调试器,它们可以作为一个整体来使用。
- 抽象工厂模式适用于提供产品类的库,所有的产品都以同样的接口出现,这样客户端就不依赖于具体的实现。这有助于在添加新产品时,不需要修改现有的客户端代码。
- 当客户端不关心产品实例如何被创建,以及实现的具体细节时,可以使用抽象工厂模式。这样,客户端只需通过工厂接口来请求所需的产品,而无需了解产品的创建过程。
- 如果系统的产品有多于一个的产品族,而系统只消费其中某一族的产品,那么抽象工厂模式可以用来定义多个产品,并在一个工厂里聚合多个同类产品。
- 抽象工厂模式主要解决的是接口选择的问题,即提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
总结
这三种模式都是用于创建对象的设计模式,但它们的重点和适用场景有所不同。简单工厂适用于简单的对象创建场景,工厂方法适用于产品等级结构复杂的情况,而抽象工厂则适用于多产品族和产品系列的场景。