简单工厂模式,它提供了一个用于创建对象的接口,但具体创建的对象类型可以在运行时决定。这种模式通常用于创建具有共同接口的对象,并且可以根据客户端代码中的参数或配置来选择要创建的具体对象类型。
在简单工厂模式中,有一个专门的类负责创建其他类的实例,这个类称为工厂类。被创建的实例通常都具有共同的父类。工厂类中有一个用于创建对象的静态工厂方法,系统可以根据该方法所传入的参数来动态决定应该创建出哪一个产品类的实例。
以汽车生产为例,简单工厂模式可以模拟该生产过程。我们将汽车抽象为一个产品接口,不同品牌的汽车则具体实现该接口并提供各自的功能。工厂类负责根据传入的品牌参数来创建相应的汽车对象。
简单工厂模式的使用场景:
1、创建对象的场景:当一个对象需要由另一个对象来创建时,而且创建对象的算法会改变,这时就可以使用简单工厂模式。例如,当一个对象需要调用另一个对象的方法时,若直接通过new关键字来创建一个对象,然后再调用它的方法,这样做不太合适。如果需求变化了,如要将这个对象改为另一个类的实例,则需要修改所有使用new关键字的代码,这显然是不好的。
2、解耦的场景:简单工厂模式的目的是实现解耦,将对象的创建和使用分开。即应用程序将对象的创建和初始化职责交给工厂对象。
3、业务变化的场景:当类本身有很多子类,并且经常性发生变化时,也可以考虑使用简单工厂模式。
4、降低代码重复率的场景:如果对象的创建过程比较复杂,并且很多地方都用到了,那么很可能出现很多重复的代码。通过统一将创建对象的代码放到工厂里面统一管理,可以减少代码的重复率,同时也方便维护。
请注意,在实际应用中,使用简单工厂模式时需要注意工厂类职责不应过重。在实际开发中,简单工厂模式被广泛应用于许多场景,例如:
1、构建数据库连接池:通过简单工厂模式可以方便地创建数据库连接池,而不必关心连接池的具体实现细节。
2、生成PDF文档:可以使用简单工厂模式来生成PDF文档,客户端只需要传入所需的参数即可。
3、读取文件:可以使用简单工厂模式来读取不同类型的文件,客户端只需要传入文件路径和文件类型即可。
总之,简单工厂模式是一种灵活且易于使用的创建型设计模式,适用于许多场景。
简单工厂模式的创建步骤如下:
1、声明一个抽象类(接口),以及对应的抽象方法,这些方法将由实现类分别去实现。
2、创建具体实现类,实现抽象方法。这些类通常是与客户端直接交互的对象。
3、创建一个简单工厂类,声明一个静态方法,根据传入的不同的类型来确定创建抽象类的具体实现类。
4、客户端通过工厂类获取实例对象。客户端并不直接创建对象,而是通过调用简单工厂模式的方法来统一创建对象。
简单工厂模式的优点:
1、实现对象创建和使用分离:简单工厂模式中,工厂类包含了必要的判断逻辑,根据客户端传入的参数决定创建哪一个具体产品类的实例。这样,客户端就无需直接创建产品对象,只需要消费产品即可,实现了对象创建和使用分离。
2、减少记忆量:由于客户端无需知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,这在一些复杂的类名情况下,可以减少使用者的记忆量。
3、提高灵活性:通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
简单工厂模式的缺点:
1、职责过重:由于工厂类集中了所有产品的创建逻辑,一旦该类不能正常工作,整个系统都会受到影响。
2、增加系统复杂度和理解难度:使用简单工厂模式势必会增加系统中类的个数(引入了新的工厂类),这会增加系统的复杂度和理解难度。
3、系统扩展困难:如果增加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

以下是一个示例,展示了如何在C#中实现简单工厂模式:
- // 接口
- public interface Shape
- {
- void Draw();
- }
-
- // 实现接口的实体类
- public class Circle : Shape
- {
- public void Draw()
- {
- Console.WriteLine("绘制一个圆形");
- }
- }
-
- public class Rectangle : Shape
- {
- public void Draw()
- {
- Console.WriteLine("绘制一个矩形");
- }
- }
-
- // 工厂类,创建实体类的对象
- public class ShapeFactory
- {
- // 通过GetShape方法来根据传入的字符串来返回相应的Shape类型的对象
- public Shape GetShape(string type)
- {
- if (type == "Circle")
- {
- return new Circle();
- }
- else if (type == "Rectangle")
- {
- return new Rectangle();
- }
- else
- {
- throw new ArgumentException("无效的图形类型");
- }
- }
- }
- //使用这个工厂,你可以在运行时决定创建哪种类型的 Shape。例如:
- class FactoryPatternDemo
- {
- static void Main(string[] args)
- {
- ShapeFactory shapeFactory = new ShapeFactory();
- Shape shape1 = shapeFactory.GetShape("Circle");
- shape1.Draw(); // 输出"绘制一个圆形"
- Shape shape2 = shapeFactory.GetShape("Rectangle");
- shape2.Draw(); // 输出"绘制一个矩形"
- }
- }
以下是一个示例,展示了如何在Java中实现简单工厂模式:
- // 接口
- public interface Shape {
- void draw();
- }
- // 实现接口的实体类
- public class Circle implements Shape {
- @Override
- public void draw() {
- System.out.println("绘制一个圆形");
- }
- }
-
- public class Rectangle implements Shape {
- @Override
- public void draw() {
- System.out.println("绘制一个矩形");
- }
- }
- // 工厂类,创建实体类的对象
- public class ShapeFactory {
- // 通过getShape方法来根据传入的字符串来返回相应的Shape类型的对象
- public Shape getShape(String type) {
- if (type.equalsIgnoreCase("CIRCLE")) {
- return new Circle();
- } else if (type.equalsIgnoreCase("RECTANGLE")) {
- return new Rectangle();
- } else {
- throw new IllegalArgumentException("无效的形状类型");
- }
- }
- }
- //然后我们就可以这样使用这个工厂类创建Shape对象:
- public class FactoryPatternDemo {
- public static void main(String[] args) {
- ShapeFactory shapeFactory = new ShapeFactory();
- Shape shape1 = shapeFactory.getShape("CIRCLE");
- shape1.draw(); // 输出"绘制一个圆形"
- Shape shape2 = shapeFactory.getShape("RECTANGLE");
- shape2.draw(); // 输出"绘制一个矩形"
- }
- }
在JavaScript 中,它使用一个共同的接口来实例化不同类型的对象,而无需直接使用具体类。在工厂模式中,您可以创建一个工厂类来负责创建对象,而无需暴露创建逻辑。
以下是一个示例,展示了如何在JavaScript中实现简单工厂模式:
- // Car 接口
- class Car {
- constructor(name) {
- this.name = name;
- }
-
- start() {
- console.log(this.name + ' started');
- }
-
- stop() {
- console.log(this.name + ' stopped');
- }
- }
-
- // CarFactory 工厂类
- class CarFactory {
- constructor() {
- this.cars = {};
- }
-
- // 创建轿车对象
- createCar(name, type='Sedan') {
- if (!this.cars[type]) {
- this.cars[type] = new Car(type);
- }
- return this.cars[type];
- }
-
- // 创建卡车对象
- createTruck(name, type='Pickup') {
- if (!this.cars[type]) {
- this.cars[type] = new Car(type);
- }
- return this.cars[type];
- }
- }
- //接下来,我们使用 CarFactory 工厂类来制造不同类型的汽车:
- // 创建 CarFactory 实例
- const carFactory = new CarFactory();
-
- // 制造轿车
- const sedan = carFactory.createCar('Alice', 'Sedan');
- sedan.start(); // 输出 "Sedan started"
- sedan.stop(); // 输出 "Sedan stopped"
-
- // 制造卡车
- const truck = carFactory.createCar('Bob', 'Truck');
- truck.start(); // 输出 "Pickup started"
- truck.stop(); // 输出 "Pickup stopped"
在C++中,可以通过以下步骤来实现简单工厂模式:
1、定义一个抽象基类(或接口),其中包含所有派生类的公共方法。这个抽象基类可以看作是工厂的公共接口,它不知道具体对象的类型。
2、创建多个派生类,这些派生类实现了抽象基类中的所有公共方法,每个派生类具有不同的状态和行为。
3、创建一个工厂类,它包含一个用于创建对象的纯虚函数。这个纯虚函数根据传入的参数类型来创建相应的派生类对象,并返回该对象的指针。
4、在客户端代码中,通过调用工厂类的纯虚函数来创建对象。由于客户端代码不知道具体对象的类型,因此可以使用抽象基类的指针来操作这些对象。
以下是一个示例,展示了如何在C++中实现简单工厂模式:
- #include
-
- // 抽象基类
- class Shape {
- public:
- virtual void draw() = 0;
- };
-
- // 圆形派生类
- class Circle : public Shape {
- public:
- void draw() override {
- std::cout << "绘制圆形" << std::endl;
- }
- };
-
- // 矩形派生类
- class Rectangle : public Shape {
- public:
- void draw() override {
- std::cout << "绘制矩形" << std::endl;
- }
- };
-
- // 工厂类
- class ShapeFactory {
- public:
- // 根据传入的参数类型来创建相应的对象,并返回该对象的指针
- static Shape* createShape(const std::string& type) {
- if (type == "Circle") {
- return new Circle();
- } else if (type == "Rectangle") {
- return new Rectangle();
- } else {
- throw std::invalid_argument("无效的形状类型");
- }
- }
- };
-
- int main() {
- // 创建圆形对象
- Shape* circle = ShapeFactory::createShape("Circle");
- circle->draw(); // 输出"绘制圆形"
- delete circle;
-
- // 创建矩形对象
- Shape* rectangle = ShapeFactory::createShape("Rectangle");
- rectangle->draw(); // 输出"绘制矩形"
- delete rectangle;
-
- return 0;
- }
在Python中,工厂模式通常是通过函数或类来创建其他类的实例。简单工厂模式是一种常见的工厂模式,它通过一个单独的工厂类来创建产品对象,这个工厂类一般用来创建与环境有关的具体产品。
下面是一个Python中简单工厂模式的例子:
- class Product(object):
- def operation(self):
- pass
-
- class ConcreteProduct1(Product):
- def operation(self):
- return "ConcreteProduct1 operation"
-
- class ConcreteProduct2(Product):
- def operation(self):
- return "ConcreteProduct2 operation"
-
- class Factory:
- @staticmethod
- def create_product(product_type):
- if product_type == "type1":
- return ConcreteProduct1()
- elif product_type == "type2":
- return ConcreteProduct2()
- else:
- return None
-
- def client_code(factory=Factory):
- product = factory.create_product("type1")
- print(product.operation())
-
- if __name__ == "__main__":
- client_code()
以下是一个示例,展示了如何在go中实现简单工厂模式:
- // 抽象产品接口
- interface Product {
- void use();
- }
-
- // 具体产品类1
- class ConcreteProduct1 implements Product {
- public void use() {
- System.out.println("使用具体产品1");
- }
- }
-
- // 具体产品类2
- class ConcreteProduct2 implements Product {
- public void use() {
- System.out.println("使用具体产品2");
- }
- }
-
- // 工厂类
- class Factory {
- public Product createProduct(String type) {
- if (type.equals("product1")) {
- return new ConcreteProduct1();
- } else if (type.equals("product2")) {
- return new ConcreteProduct2();
- } else {
- throw new IllegalArgumentException("无效的产品类型");
- }
- }
- }
-
- // 客户端代码
- public class Client {
- public static void main(String[] args) {
- Factory factory = new Factory();
- Product product1 = factory.createProduct("product1");
- product1.use(); // 输出:使用具体产品1
- Product product2 = factory.createProduct("product2");
- product2.use(); // 输出:使用具体产品2
- }
- }
以下是一个示例,展示了如何在PHP中实现简单工厂模式:
-
-
- // 产品接口
- interface Product {
- public function useProduct();
- }
-
- // 具体产品类 1
- class ConcreteProduct1 implements Product {
- public function useProduct() {
- echo "使用具体产品1\n";
- }
- }
-
- // 具体产品类 2
- class ConcreteProduct2 implements Product {
- public function useProduct() {
- echo "使用具体产品2\n";
- }
- }
-
- // 工厂类
- class Factory {
- public static function createProduct($type) {
- if ($type === 'product1') {
- return new ConcreteProduct1();
- } elseif ($type === 'product2') {
- return new ConcreteProduct2();
- } else {
- throw new Exception('无效的产品类型');
- }
- }
- }
-
- // 客户端代码
- function clientCode() {
- $product1 = Factory::createProduct('product1');
- $product1->useProduct(); // 输出:使用具体产品1
-
- $product2 = Factory::createProduct('product2');
- $product2->useProduct(); // 输出:使用具体产品2
- }
-
- // 调用客户端代码
- clientCode();
- ?>
《完结》