提供网站建设的功能,七牛 wordpress 插件,wordpress媒体库 外链,东台网络推广目录
一、工厂模式
1.1 工厂模式的定义
1.2 工厂模式的设计意图
1.3 工厂模式主要解决的问题
1.4 工厂模式的缺点
1.5 实际的应用案例
1. 数据库连接池
2. 图形用户界面#xff08;GUI#xff09;组件
3. 文件操作
二、各种工厂模式的变形
1.1 简单工厂模式#…目录
一、工厂模式
1.1 工厂模式的定义
1.2 工厂模式的设计意图
1.3 工厂模式主要解决的问题
1.4 工厂模式的缺点
1.5 实际的应用案例
1. 数据库连接池
2. 图形用户界面GUI组件
3. 文件操作
二、各种工厂模式的变形
1.1 简单工厂模式
1.2 工厂方法模式
1.3 抽象工厂模式
三、基本的代码实现 今天重点梳理下设计模式中工厂模式的相关知识点。
一、工厂模式
1.1 工厂模式的定义
工厂模式Factory Pattern最常用的设计模式之一。这种类型的设计模式属于创建型模式它提供了一种创建对象的最佳方式。
在工厂模式中我们在创建对象时不会对客户端暴露创建逻辑并且是通过使用一个共同的接口来指向新创建的对象。
1.2 工厂模式的设计意图
工厂模式的主要设计意图是将对象的创建过程与使用过程分离从而使得客户端代码无需知道具体创建什么类型的对象。这种分离有助于降低系统的耦合度提高代码的可维护性和扩展性。
工厂模式通过以下方式实现这一目标
1. 解耦对象的创建 - 工厂模式允许将对象的创建过程封装在一个单独的类或一组类中即工厂而不是直接在客户端代码中实例化对象。 - 这样可以避免在客户端代码中硬编码具体的对象类型使得代码更加灵活和可复用。
2. 支持多种产品类型 - 工厂模式可以根据不同的情况动态地选择要创建的对象类型而客户端只需关心如何使用产品而不必关心产品的具体实现细节。 - 这种灵活性使得工厂模式适用于需要根据运行时条件来决定创建哪种产品的情况。
3. 隐藏复杂的产品创建逻辑 - 如果对象的创建过程非常复杂或者涉及到多个步骤工厂模式可以通过将这些逻辑封装在工厂类中来简化客户端代码。 - 客户端代码只需要调用工厂类的一个简单方法就可以得到所需的对象而不需要了解具体的创建过程。
4. 易于添加新产品类型 - 当需要添加新的产品类型时只需增加一个新的工厂类即可而无需修改现有的客户端代码。 - 这种开闭原则Open-Closed Principle的遵循使得系统更容易进行扩展。
5. 便于单元测试 - 由于工厂模式将对象的创建过程隔离出来因此在编写单元测试时可以方便地替换实际的产品对象为模拟对象mock object以减少依赖并提高测试覆盖率。
1.3 工厂模式主要解决的问题
对象的创建过于复杂如果一个对象的创建涉及到很多步骤或者需要复杂的条件判断那么工厂模式可以帮助将这些逻辑封装在一个地方使得客户端代码更简洁。过度依赖具体的产品类如果没有使用工厂模式客户端代码可能会直接引用具体的产品类这会导致高度的耦合。工厂模式可以将这种依赖关系转移到工厂类上从而降低耦合度。难以扩展新类型的产品如果系统中有很多不同种类的产品而且可能还会继续增加那么工厂模式可以提供一种统一的方式来管理这些产品使得添加新类型的产品变得相对容易。需要控制对象的生命周期在某些情况下可能需要对对象的创建、使用和销毁进行更精细的控制。工厂模式可以通过返回不同类型的产品实例来实现这一点。
1.4 工厂模式的缺点 增加了代码复杂性引入工厂模式后系统中会多出一个或多个工厂类以及可能的产品类这可能会增加代码的复杂性尤其是在大型项目中。 违反开闭原则尽管工厂模式有助于扩展新的产品类型但如果需要改变已有的工厂类来支持新类型就违背了开闭原则。这意味着每次添加新产品类型时都可能需要修改工厂类的代码。 可能增加额外的性能开销工厂模式通常涉及一些条件判断或反射操作来决定创建哪种产品对象这可能会带来一些额外的性能开销。 难以理解复杂的工厂结构在某些情况下工厂模式可能导致工厂类的结构变得复杂特别是当存在大量产品类型和工厂类时。这可能会使代码更难理解和维护。 不适合简单的场景如果只需要创建一种产品类型或者创建过程非常简单那么使用工厂模式可能会显得过于复杂此时直接使用new关键字创建对象可能是更好的选择。
1.5 实际的应用案例
1. 数据库连接池
在数据库应用程序中通常需要频繁地创建和销毁数据库连接。为了提高性能和减少资源消耗可以使用连接池来管理这些连接。连接池就是一个典型的工厂模式应用。
首先定义一个DatabaseConnection接口表示数据库连接的抽象类型。然后创建多个实现这个接口的具体类例如MySQLConnection、PostgreSQLConnection等它们分别代表与不同类型的数据库建立连接。
接下来创建一个DatabaseConnectionFactory接口声明一个方法createConnection()用于创建数据库连接。针对每种数据库类型都创建一个具体的工厂类如MySQLConnectionFactory、PostgreSQLConnectionFactory等它们实现了DatabaseConnectionFactory接口并且在createConnection()方法中返回对应的数据库连接实例。
客户端代码只需要知道如何使用DatabaseConnection接口而不必关心具体使用的数据库类型。当需要创建新的数据库连接时只需调用相应的工厂类的createConnection()方法即可。
2. 图形用户界面GUI组件
在图形用户界面编程中工厂模式也可以用来创建各种UI组件。例如我们可以定义一个Button接口表示按钮的抽象类型。然后为每个平台如Windows、MacOS、Linux等创建一个实现Button接口的具体类比如WindowsButton、MacOSButton、LinuxButton等。
接着定义一个ButtonFactory接口声明一个方法createButton()用于创建按钮。为每个平台创建一个具体的工厂类如WindowsButtonFactory、MacOSButtonFactory、LinuxButtonFactory等它们实现了ButtonFactory接口并且在createButton()方法中返回对应的按钮实例。
客户端代码可以根据运行时环境选择合适的工厂类来创建按钮。这样可以使代码更加灵活更容易适应不同平台的需求。
3. 文件操作
在处理文件时可以使用工厂模式来根据文件的扩展名创建适当的文件处理器。首先定义一个FileProcessor接口包含读取、写入等操作。然后为每种文件格式创建一个实现FileProcessor接口的具体类如TextFileProcessor、ImageFileProcessor、AudioFileProcessor等。
接下来定义一个FileProcessorFactory接口声明一个方法createProcessor(filename)用于根据文件名创建文件处理器。为每种文件格式创建一个具体的工厂类如TextFileProcessorFactory、ImageFileProcessorFactory、AudioFileProcessorFactory等它们实现了FileProcessorFactory接口并且在createProcessor()方法中根据文件扩展名返回对应的文件处理器实例。
客户端代码只需要知道如何使用FileProcessor接口而不必关心处理哪种类型的文件。当需要对文件进行操作时只需调用相应的工厂类的createProcessor()方法即可。
以上是三个具体的工厂模式应用案例。实际上任何需要动态创建对象并且有多种可能的产品类型的情况都可以考虑使用工厂模式。您需要一辆汽车可以直接从工厂里面提货而不用去管这辆汽车是怎么做出来的以及这个汽车里面的具体实现。Hibernate 换数据库只需换方言和驱动就可以。
二、各种工厂模式的变形
工厂模式主要有以下几种形式
1.1 简单工厂模式
定义一个工厂类该类可以根据传入的参数返回不同种类的产品实例。简单工厂模式不是Gang of Four (GoF)所定义的23种经典设计模式之一但它是一个常用的设计模式变体也被广泛称为静态工厂方法。
1.2 工厂方法模式
在抽象基类中声明一个创建产品的方法但不提供具体的实现由子类来实现这个方法。每个子类根据需要创建自己的产品类型。这种模式支持添加新的产品类型时只需要增加一个新的子类即可。
1.3 抽象工厂模式
提供一个创建一系列相关或相互依赖对象的接口而无需指定具体的类。适用于需要提供多个相关的对象系列的情况。与工厂方法模式相比抽象工厂模式更注重的是创建一组相关或相互依赖的产品。
三、基本的代码实现
下面是一个简单的工厂模式的示例使用 Java 语言来实现
// 定义一个接口或抽象类
public interface Product {void use();
}// 实现具体的产品1
public class ConcreteProduct1 implements Product {Overridepublic void use() {System.out.println(Using concrete product 1.);}
}// 实现具体的产品2
public class ConcreteProduct2 implements Product {Overridepublic void use() {System.out.println(Using concrete product 2.);}
}// 工厂类
public class Factory {// 根据传入的参数返回不同的产品public static Product createProduct(String type) {if (product1.equals(type)) {return new ConcreteProduct1();} else if (product2.equals(type)) {return new ConcreteProduct2();} else {throw new IllegalArgumentException(Invalid type);}}
}// 客户端代码
public class Client {public static void main(String[] args) {Product product1 Factory.createProduct(product1);product1.use();Product product2 Factory.createProduct(product2);product2.use();}
}
在上面的示例中我们定义了一个Product接口和两个实现了该接口的具体产品类ConcreteProduct1和ConcreteProduct2。然后我们创建了一个Factory类它有一个静态方法createProduct根据传入的字符串参数返回不同种类的产品实例。
客户端代码通过调用Factory.createProduct方法来获取需要的产品实例并使用它们。
如果你想要 Python 的示例代码下面是等效的实现
# 定义一个抽象基类
from abc import ABC, abstractmethodclass Product(ABC):abstractmethoddef use(self):pass# 实现具体的产品1
class ConcreteProduct1(Product):def use(self):print(Using concrete product 1.)# 实现具体的产品2
class ConcreteProduct2(Product):def use(self):print(Using concrete product 2.)# 工厂类
class Factory:# 根据传入的参数返回不同的产品staticmethoddef create_product(product_type):if product_type product1:return ConcreteProduct1()elif product_type product2:return ConcreteProduct2()else:raise ValueError(Invalid type)# 客户端代码
def main():product1 Factory.create_product(product1)product1.use()product2 Factory.create_product(product2)product2.use()if __name__ __main__:main()这段 Python 代码的功能与上述 Java 代码相同只是语法有所不同。在这里我们使用了 Python 的 abc 模块来定义一个抽象基类抽象类并利用 abstractmethod 装饰器来标记需要子类实现的方法。其他部分的逻辑和结构基本保持一致。
PS设计模式的梳理系列暂时告一段落。谢谢阅读。