工厂模式简介

概念

工厂模式(Factory Pattern)是一种创建型设计模式,它提供了一种封装对象实例化过程的方式,客户端只需要关注接口或抽象类,并由工厂类根据具体需求返回相应的实例。工厂模式将对象的创建与使用分离,客户端无需直接调用构造函数来创建对象。工厂模式定义了一个抽象工厂和多个具体工厂,每个具体工厂负责创建特定类型的产品。

特点

  1. 封装性:隐藏了对象实例化细节,客户端只需要与抽象接口交互。
  2. 扩展性:易于添加新产品或变更现有产品的实现。
  3. 解耦性:将客户端与具体产品之间解耦,降低了代码依赖关系。

优点

  1. 符合开闭原则:新增产品时无需修改已有代码,在扩展上更加灵活。
  2. 降低耦合度:客户端仅依赖于抽象接口而非具体实现类。
  3. 高内聚、低耦合:相关逻辑被封装在各自的具体工厂中。

缺点

  1. 增加系统复杂度:引入额外的类和层级,增加了代码量。
  2. 需要额外的工厂类:每个具体产品都需要对应一个具体工厂类。

适用场景

  1. 需要创建多个相似对象的场景。
  2. 客户端不关心实例化过程和细节,只需获取抽象接口即可的场景。

实现方式

简单工厂模式

实现原理:

  1. 定义一个接口或父类来表示产品。
  2. 创建具体产品类,它们继承自父类或实现接口。
  3. 创建一个简单工厂类,该类包含一个静态方法用于根据客户端传入的参数来创建相应的具体产品对象。

实现代码:

java 复制代码
// 接口或父类
interface Product {
    void doSomething();
}

// 具体产品A
class ConcreteProductA implements Product {
    @Override
    public void doSomething() {
        System.out.println("ConcreteProductA do something");
    }
}

// 具体产品B
class ConcreteProductB implements Product {
    @Override
    public void doSomething() {
        System.out.println("ConcreteProductB do something");
    }
}

// 简单工厂类
public class SimpleFactory {
    
    // 静态方法根据参数创建对应的具体产品对象
    public static Product createProduct(String type) {
        if (type.equals("A")) { 
            return new ConcreteProductA();
        } else if (type.equals("B")) { 
            return new ConcreteProductB();
        } else { 
            throw new IllegalArgumentException("Invalid product type.");
        }
    }
    
    public static void main(String[] args){
         Product a = SimpleFactory.createProduct("A");
         a.doSomething();
    }
}

上述代码中,我们定义了一个 Product 接口作为抽象基类,然后创建了两个具体产品类 ConcreteProductA 和 ConcreteProductB,它们都实现了 Product 接口。最后,我们创建了一个简单工厂类 SimpleFactory,其中的静态方法根据客户端传入的参数来创建相应的具体产品对象。使用简单工厂模式时存在以下问题:

  1. 违反开闭原则:每次添加新产品都需要修改工厂类中的代码。
  2. 工厂职责过重:所有产品的创建逻辑集中在一个工厂类中,导致该类变得庞大而复杂。

尽管简单工厂模式存在以上问题,但它仍然是一种常用且易于理解和实现的工厂模式。

工厂方法模式

实现原理:

  1. 定义一个接口或父类来表示产品。
  2. 创建具体产品类,它们继承自父类或实现接口。
  3. 创建一个抽象工厂接口,该接口声明了创建产品的方法。
  4. 创建多个具体工厂类,每个具体工厂类负责创建特定类型的产品。

实现代码:

java 复制代码
// 接口或父类
interface Product {
    void doSomething();
}

// 具体产品A
class ConcreteProductA implements Product {
    @Override
    public void doSomething() {
        System.out.println("ConcreteProductA do something");
    }
}

// 具体产品B
class ConcreteProductB implements Product {
    @Override
    public void doSomething() {
        System.out.println("ConcreteProductB do something");
    }
}

// 抽象工厂接口
interface Factory {
    Product createProduct();
}

// 具体工厂A用于创建具体产品A
class ConcreteFactoryA implements Factory {
    
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

// 具体工厂B用于创建具体产品B 
class ConcreteFactoryB implements Factory {

   @Override 
   public Product createProduct() { 
       return new ConcreteProductB();
   }
}

上述代码中,我们定义了一个 Product 接口作为抽象基类,然后创建了两个具体产品类 ConcreteProductA 和 ConcreteProductB,它们都实现了 Product 接口。接着,我们定义了一个抽象工厂接口 Factory,其中声明了一个用于创建产品的方法。最后,我们创建了两个具体工厂类 ConcreteFactoryA 和 ConcreteFactoryB,分别用于创建具体产品 A 和 B。

使用工厂方法模式时存在以下问题:

  1. 每次添加新产品需要同时增加对应的具体工厂类。
  2. 客户端需要知道不同的具体工厂类来获取不同类型的产品。

尽管存在以上问题,但工厂方法模式能够提供更好的扩展性和灵活性,并且符合开闭原则。客户端只需关注与特定的抽象工厂和产品进行交互即可。

抽象工厂模式

实现原理:

  1. 定义产品族接口,该接口声明了一组相关的产品。
  2. 创建多个具体产品族类,每个具体产品族类负责实现对应的抽象产品族接口。
  3. 定义抽象工厂接口,该接口声明了用于创建不同产品族对象的方法。
  4. 创建多个具体工厂类,每个具体工厂类负责创建特定类型的产品族对象。

实现代码:

java 复制代码
//产品A
interface ProductA {
    void doSomething();
}

// 具体产品A1
class ConcreteProductA1 implements ProductA {
    @Override
    public void doSomething() {
        System.out.println("ConcreteProductA1 do something");
    }
}

// 具体产品A2
class ConcreteProductA2 implements ProductA {
    @Override
    public void doSomething() {
        System.out.println("ConcreteProductA2 do something");
    }
}

// 抽象产品B 
interface ProductB { 
   void doSomething(); 
} 

// 具体产品B1 
class ConcreateProductB1 implements ProductB { 
   @Override 
   public void doSomething() { 
       System.out.println("ConcreteProductB1 do something"); 
   } 
} 

// 具体产品B2 
class ConcreateProductB2 implements ProductB { 
   @Override 
   public void doSomething() { 
       System.out.println("ConcreteProductB2 do something"); 
   } 
}

// 抽象工厂接口
interface AbstractFactory {
    ProductA createProductA();
    ProductB createProductB();
}

// 具体工厂1用于创建具体产品族1
class ConcreteFactory1 implements AbstractFactory {
    
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }
    
    @Override
    public ProductB createProductB() {
        return new ConcreateProductB1();
    }
}

// 具体工厂2用于创建具体产品族2
class ConcreteFactory2 implements AbstractFactory {

   @Override  
   public ProductA createProductA() {  
       return new ConcreteProductA2();  
   }  

  @Override   
  public ProductB createProductB() {   
      return new ConcreateProductB2();   
  }  
}

上述代码中,我们定义了两个产品接口 ProductA 和 Prodcut B,并分别实现了它们的具体产品类。然后,我们定义了一个抽象工厂接口 AbstractFactory,其中声明了两个方法用于创建不同类型的抽象产品对象。最后,我们创建了两个具体工厂类 ConcreteFactory1 和 ConcreteFactory2 分别负责创建特定的抽象产品族对象。

使用抽象工厂模式时存在以下问题:

  1. 每次添加新产品族需要同时增加对应的产品接口和具体产品类。
  2. 客户端需要知道不同的具体工厂类来获取不同类型的抽象产品。

尽管存在以上问题,但抽象工厂模式能够提供更好的扩展性和灵活性,并且符合开闭原则。客户端只需关注与特定的抽象工厂和产品进行交互即可。

相关推荐
legend_jz12 分钟前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法
drebander24 分钟前
使用 Java Stream 优雅实现List 转化为Map<key,Map<key,value>>
java·python·list
乌啼霜满天24927 分钟前
Spring 与 Spring MVC 与 Spring Boot三者之间的区别与联系
java·spring boot·spring·mvc
tangliang_cn32 分钟前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟33 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
Grey_fantasy43 分钟前
高级编程之结构化代码
java·spring boot·spring cloud
新知图书44 分钟前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
威威猫的栗子1 小时前
Python Turtle召唤童年:喜羊羊与灰太狼之懒羊羊绘画
开发语言·python
力透键背1 小时前
display: none和visibility: hidden的区别
开发语言·前端·javascript
bluefox19791 小时前
使用 Oracle.DataAccess.Client 驱动 和 OleDB 调用Oracle 函数的区别
开发语言·c#