原创 悟 老汉聊技术 2023-04-16 00:00 发表于四川
工厂模式是一种常用的创建型设计模式,它通过一个共同的接口来创建一些相关或相互依赖的对象,而无需指定其具体的类。
一、工厂模式分类
工厂模式主要分为以下几种:
-
简单工厂模式:由一个工厂类根据传入的参数,决定创建哪种产品类的实例。
-
工厂方法模式:定义一个用于创建对象的接口,让子类决定实例化哪个类。使一个类的实例化延迟到其子类。
-
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
二、工厂模式详解
下面分别详细讲解每一种工厂模式,并结合实际应用场景举例,给出示例代码。
-
简单工厂模式
简单工厂模式又叫静态工厂方法模式,它属于类创建型模式。简单工厂模式是由一个工厂类根据传入的参数,动态决定创建哪种产品类的实例。简单工厂模式适用于工厂类负责创建的对象比较少的场景。
应用场景:
假设一个系统需要记录不同种类的日志信息,例如文件日志、数据库日志、控制台日志等。系统需要提供一个可以按照用户要求创建不同种类日志的工厂类。
示例代码:
首先定义一个日志接口ILog,它包含一个写日志的方法writeLog():
public interface ILog {
void writeLog();
}
然后定义三个具体的日志类:FileLog、DatabaseLog和ConsoleLog:
public class FileLog implements ILog {
public void writeLog() {
System.out.println("记录文件日志...");
}
}
public class DatabaseLog implements ILog {
public void writeLog() {
System.out.println("记录数据库日志...");
}
}
public class ConsoleLog implements ILog {
public void writeLog() {
System.out.println("记录控制台日志...");
}
}
最后,定义一个简单工厂类,根据传入的参数创建不同种类的日志对象:
public class LoggerFactory {
public static ILog createLogger(String type) {
if ("file".equals(type)) {
return new FileLog();
} else if ("database".equals(type)) {
return new DatabaseLog();
} else if ("console".equals(type)) {
return new ConsoleLog();
} else {
throw new IllegalArgumentException("unsupported type: " + type);
}
}
}
使用时,可以通过传入不同的参数来创建不同种类的日志对象:
public class Main {
public static void main(String[] args) {
ILog log = LoggerFactory.createLogger("file");
log.writeLog();
}
}
-
工厂方法模式
工厂方法模式是一种常见的创建型设计模式,它定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法模式使一个类的实例化延迟到其子类。
应用场景:
假设一个系统需要记录不同种类的日志信息,例如文件日志、数据库日志、控制台日志等。系统需要提供一个可以按照用户要求创建不同种类日志的工厂接口,并让具体工厂类去实现不同种类的日志对象创建。
示例代码:
首先定义一个日志接口ILog,它包含一个写日志的方法writeLog():
public interface ILog {
void writeLog();
}
然后定义三个具体的日志类:FileLog、DatabaseLog和ConsoleLog:
public class FileLog implements ILog {
public void writeLog() {
System.out.println("记录文件日志...");
}
}
public class DatabaseLog implements ILog {
public void writeLog() {
System.out.println("记录数据库日志...");
}
}
public class ConsoleLog implements ILog {
public void writeLog() {
System.out.println("记录控制台日志...");
}
}
接下来定义一个日志工厂接口ILoggerFactory,它包含一个创建日志对象的工厂方法createLogger():
public interface ILoggerFactory {
ILog createLogger();
}
然后定义三个具体的日志工厂类:FileLoggerFactory、DatabaseLoggerFactory和ConsoleLoggerFactory,分别用于创建FileLog、DatabaseLog和ConsoleLog对象:
public class FileLoggerFactory implements ILoggerFactory {
public ILog createLogger() {
return new FileLog();
}
}
public class DatabaseLoggerFactory implements ILoggerFactory {
public ILog createLogger() {
return new DatabaseLog();
}
}
public class ConsoleLoggerFactory implements ILoggerFactory {
public ILog createLogger() {
return new ConsoleLog();
}
}
使用时,可以通过不同的具体工厂类创建不同种类的日志对象:
public class Main {
public static void main(String[] args) {
ILoggerFactory factory = new FileLoggerFactory();
ILog log = factory.createLogger();
log.writeLog();
}
}
-
抽象工厂模式
抽象工厂模式是一种常用的创建型设计模式,它提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。抽象工厂模式适用于需要创建一组相关或相互依赖的对象时,可以通过一个工厂接口来实现。
应用场景:
假设一个系统需要提供一个图形界面库,其中包含不同种类的界面元素,例如按钮、文本框、复选框等。每种元素又分为不同的主题风格,例如 Windows 风格、Mac 风格、Linux 风格等。系统需要提供一个抽象工厂来创建不同种类的界面元素,使得这些元素能够和主题风格相对应。
示例代码:
首先定义抽象产品接口IButton、ITextField和ICheckBox,它们都包含一个显示的方法display():
public interface IButton {
void display();
}
public interface ITextField {
void display();
}
public interface ICheckBox {
void display();
}
然后定义三种主题风格下的具体产品类:WindowsButton、WindowsTextField、WindowsCheckBox、MacButton、MacTextField、MacCheckBox、LinuxButton、LinuxTextField和LinuxCheckBox:
public class WindowsButton implements IButton {
public void display() {
System.out.println("显示Windows风格按钮...");
}
}
public class WindowsTextField implements ITextField {
public void display() {
System.out.println("显示Windows风格文本框...");
}
}
public class WindowsCheckBox implements ICheckBox {
public void display() {
System.out.println("显示Windows风格复选框...");
}
}
public class MacButton implements IButton {
public void display() {
System.out.println("显示Mac风格按钮...");
}
}
public class MacTextField implements ITextField {
public void display() {
System.out.println("显示Mac风格文本框...");
}
}
public class MacCheckBox implements ICheckBox {
public void display() {
System.out.println("显示Mac风格复选框...");
}
}
public class LinuxButton implements IButton {
public void display() {
System.out.println("显示Linux风格按钮...");
}
}
public class LinuxTextField implements ITextField {
public void display() {
System.out.println("显示Linux风格文本框...");
}
}
public class LinuxCheckBox implements ICheckBox {
public void display() {
System.out.println("显示Linux风格复选框...");
}
}
接下来定义一个抽象工厂接口IGUIFactory,它包含三个工厂方法:createButton()、createTextField()和createCheckBox(),用于创建不同主题风格下的按钮、文本框和复选框对象:
public interface IGUIFactory {
IButton createButton();
ITextField createTextField();
ICheckBox createCheckBox();
}
然后定义三个具体的主题风格工厂类:WindowsGUIFactory、MacGUIFactory和LinuxGUIFactory,分别用于创建Windows风格、Mac风格和Linux风格下的按钮、文本框和复选框对象:
public class WindowsGUIFactory implements IGUIFactory {
public IButton createButton() {
return new WindowsButton();
}
public ITextField createTextField() {
return new WindowsTextField();
}
public ICheckBox createCheckBox() {
return new WindowsCheckBox();
}
}
public class MacGUIFactory implements IGUIFactory {
public IButton createButton() {
return new MacButton();
}
public ITextField createTextField() {
return new MacTextField();
}
public ICheckBox createCheckBox() {
return new MacCheckBox();
}
}
public class LinuxGUIFactory implements IGUIFactory {
public IButton createButton() {
return new LinuxButton();
}
public ITextField createTextField() {
return new LinuxTextField();
}
public ICheckBox createCheckBox() {
return new LinuxCheckBox();
}
}
使用时,可以通过不同的具体工厂类创建不同主题风格下的界面元素对象:
public class Main {
public static void main(String[] args) {
IGUIFactory factory = new WindowsGUIFactory();
IButton button = factory.createButton();
ITextField textField = factory.createTextField();
ICheckBox checkBox = factory.createCheckBox();
button.display();
textField.display();
checkBox.display();
factory = new MacGUIFactory();
button = factory.createButton();
textField = factory.createTextField();
checkBox = factory.createCheckBox();
button.display();
textField.display();
checkBox.display();
factory = new LinuxGUIFactory();
button = factory.createButton();
textField = factory.createTextField();
checkBox = factory.createCheckBox();
button.display();
textField.display();
checkBox.display();
}
}
上面的代码中,我们先创建了一个WindowsGUIFactory工厂对象,然后通过它分别创建了一个Windows风格的按钮、文本框和复选框,并调用了它们的display()方法进行显示。接着,我们又创建了一个MacGUIFactory工厂对象,通过它创建了一个Mac风格的按钮、文本框和复选框,并调用了它们的display()方法进行显示。最后,我们又创建了一个LinuxGUIFactory工厂对象,通过它创建了一个Linux风格的按钮、文本框和复选框,并调用了它们的display()方法进行显示。
在这个例子中,我们使用了工厂方法模式的一种变体:抽象工厂模式。它与简单工厂模式、工厂方法模式的区别在于,它不仅可以创建一个对象,而是可以创建一组相关或相互依赖的对象。在这个例子中,每个具体的GUI工厂类都可以创建一组相互依赖的界面元素对象,例如WindowsGUIFactory创建的是Windows风格的按钮、文本框和复选框对象。
抽象工厂模式通常适用于以下情况:
-
系统需要一组相关或相互依赖的对象,并且这些对象的创建过程需要统一管理。
-
系统不应依赖于产品类实例如何被创建、组合和表达的细节,这些细节应该被封装在一个共同的接口中。
-
系统中有多个产品族,而每次只使用其中某一族产品。例如本例中,我们创建了Windows、Mac和Linux三个产品族,但每次只使用其中的一个。
抽象工厂模式的优点包括:
-
抽象工厂模式将具体产品的类名封装起来,使得客户端不需要知道它们的实现细节,只需要知道它们的共同接口即可。
-
抽象工厂模式使得客户端不依赖于具体产品类,而是依赖于抽象工厂接口和抽象产品接口,这样可以在不修改客户端代码的情况下改变具体工厂类和产品类。
接下来,我们来看一个更加实际的例子,使用抽象工厂模式创建一个跨平台的UI组件库。
假设我们要创建一个UI组件库,其中包括按钮、文本框和标签等常见的组件,我们希望它可以在Windows、Mac和Linux等多个平台上运行,并且在不同平台上展现出对应的UI风格。为了实现这个功能,我们可以使用抽象工厂模式来设计组件库的结构。
首先,我们定义一个抽象工厂接口,用于创建UI组件:
public interface IGUIFactory {
IButton createButton();
ITextField createTextField();
ILabel createLabel();
}
然后,我们定义各个具体的工厂类,每个工厂类都可以创建一组相互依赖的UI组件:
public class WindowsGUIFactory implements IGUIFactory {
public IButton createButton() {
return new WindowsButton();
}
public ITextField createTextField() {
return new WindowsTextField();
}
public ILabel createLabel() {
return new WindowsLabel();
}
}
public class MacGUIFactory implements IGUIFactory {
public IButton createButton() {
return new MacButton();
}
public ITextField createTextField() {
return new MacTextField();
}
public ILabel createLabel() {
return new MacLabel();
}
}
public class LinuxGUIFactory implements IGUIFactory {
public IButton createButton() {
return new LinuxButton();
}
public ITextField createTextField() {
return new LinuxTextField();
}
public ILabel createLabel() {
return new LinuxLabel();
}
}
其中,每个具体工厂类都实现了IGUIFactory接口,并且分别创建了与平台对应的UI组件对象。
接着,我们定义UI组件的抽象接口:
public interface IButton {
void display();
}
public interface ITextField {
void display();
}
public interface ILabel {
void display();
}
然后,我们定义各个具体的UI组件类:
public class WindowsButton implements IButton {
public void display() {
System.out.println("Windows style button.");
}
}
public class WindowsTextField implements ITextField {
public void display() {
System.out.println("Windows style text field.");
}
}
public class WindowsLabel implements ILabel {
public void display() {
System.out.println("Windows style label.");
}
}
public class MacButton implements IButton {
public void display() {
System.out.println("Mac style button.");
}
}
public class MacTextField implements ITextField {
public void display() {
System.out.println("Mac style text field.");
}
}
public class MacLabel implements ILabel {
public void display() {
System.out.println("Mac style label.");
}
}
public class LinuxButton implements IButton {
public void display() {
System.out.println("Linux style button.");
}
}
public class LinuxTextField implements ITextField {
public void display() {
System.out.println("Linux style text field.");
}
}
public class LinuxLabel implements ILabel {
public void display() {
System.out.println("Linux style label.");
}
}
最后,我们可以使用抽象工厂模式来创建UI组件库的对象,然后在不同的平台上使用不同的具体工厂类来创建对应的UI组件。例如:
public class Application {
private IGUIFactory factory;
public Application(IGUIFactory factory) {
this.factory = factory;
}
public void createUI() {
IButton button = factory.createButton();
ITextField textField = factory.createTextField();
ILabel label = factory.createLabel();
button.display();
textField.display();
label.display();
}
}
public class Client {
public static void main(String[] args) {
// 创建Windows风格的UI组件库
IGUIFactory windowsFactory = new WindowsGUIFactory();
Application windowsApp = new Application(windowsFactory);
windowsApp.createUI();
// 创建Mac风格的UI组件库
IGUIFactory macFactory = new MacGUIFactory();
Application macApp = new Application(macFactory);
macApp.createUI();
// 创建Linux风格的UI组件库
IGUIFactory linuxFactory = new LinuxGUIFactory();
Application linuxApp = new Application(linuxFactory);
linuxApp.createUI();
}
}
在上面的代码中,我们首先创建了三个具体的工厂类,分别代表了Windows、Mac和Linux三个平台。然后,我们使用这些工厂类创建了三个不同的Application对象,并且调用了每个对象的createUI()方法来创建UI组件并展示出来。
在Windows平台上运行上述代码的输出结果如下所示:
cssCopy code
Windows style button.
Windows style text field.
Windows style label.
在Mac平台上运行上述代码的输出结果如下所示:
Mac style button.
Mac style text field.
Mac style label.
在Linux平台上运行上述代码的输出结果如下所示:
Linux style button.
Linux style text field.
Linux style label.
从输出结果可以看出,不同平台的UI组件对象的具体实现是不同的,但是它们都实现了相同的抽象接口。这种设计可以使得我们的UI组件库具有良好的可扩展性,如果我们要支持更多的平台,只需要添加对应的具体工厂类即可
三、总结
在前面的讨论中,我们讲解了工厂模式的基本概念和常见的几种类型,下面我们再介绍一些实际应用场景,以及如何选择适合的工厂模式。
-
实际应用场景
工厂模式在很多实际应用场景中都得到了广泛的应用。下面是一些实际应用场景的示例:
-
数据库连接池。在大多数 Web 应用程序中,数据库连接池都是必需的。通过使用工厂模式,我们可以创建一个可以管理连接的对象池,并在需要时分配连接。这种方法可以避免每次需要连接数据库时都创建一个新连接的开销。
-
文件读取器。在处理文件时,可能需要根据文件类型创建不同的读取器。通过使用工厂模式,我们可以根据文件类型创建不同的文件读取器,从而实现可扩展性和灵活性。
-
网络传输协议。在开发网络应用程序时,可能需要根据不同的传输协议创建不同的对象。通过使用工厂模式,我们可以轻松地根据需要创建不同类型的对象。
-
如何选择适合的工厂模式
在实际应用中,我们需要根据具体情况选择适合的工厂模式。下面是一些指导原则:
-
简单工厂模式。如果只需要创建一个类型的对象,或者对象的创建逻辑比较简单,可以使用简单工厂模式。
-
工厂方法模式。如果需要创建多个相关的对象,并且它们之间的差异比较大,可以使用工厂方法模式。这种模式可以根据需要创建不同的工厂类,每个工厂类可以创建不同的对象。
-
抽象工厂模式。如果需要创建多个相关的对象,并且这些对象之间有复杂的关系,可以使用抽象工厂模式。这种模式可以创建一组相关的对象,并且这些对象之间的关系可以在运行时确定。
综上所述,工厂模式是一种非常常用的设计模式,可以提高代码的可扩展性、灵活性和可维护性。在实际应用中,我们需要根据具体情况选择适合的工厂模式。
本文链接:https://my.lmcjl.com/post/8677.html
4 评论