聂风精密传动定制 發表於 2025-6-22 01:57:00

设计模式-工厂模式

<h3 id="什么是工厂模式">什么是工厂模式?</h3>
<p>工厂模式(Factory Pattern)是一种创建型设计模式,它将对象的创建和使用分离,通过工厂类来负责创建对象。这种模式可以降低代码间的耦合度,提高可维护性和可扩展性。</p>
<p><strong>一、核心思想</strong></p>
<ul>
<li><strong>将对象创建逻辑封装在工厂类中</strong>,客户端无需直接实例化对象,而是通过工厂获取。</li>
<li><strong>遵循依赖倒置原则</strong>:依赖抽象而非具体实现。</li>
</ul>
<p><strong>二、工厂模式的三种形态</strong></p>
<p><strong>1. 简单工厂(Simple Factory)</strong></p>
<ul>
<li><strong>特点</strong>:静态工厂方法,创建逻辑集中在一个工厂类。</li>
<li><strong>缺点</strong>:不符合开闭原则,新增产品需修改工厂类。</li>
</ul>
<p><strong>2. 工厂方法(Factory Method)</strong></p>
<ul>
<li><strong>特点</strong>:定义抽象工厂接口,具体产品由子类工厂创建。</li>
<li><strong>优点</strong>:符合开闭原则,新增产品只需添加新的工厂子类。</li>
</ul>
<p><strong>3. 抽象工厂(Abstract Factory)</strong></p>
<ul>
<li><strong>特点</strong>:创建产品家族,每个具体工厂负责创建一系列相关产品。</li>
<li><strong>适用场景</strong>:系统需要独立于产品的创建、组合和表示时。</li>
</ul>
<h3 id="工厂模式的优缺点">工厂模式的优缺点</h3>
<ul>
<li><strong>优点</strong></li>
</ul>
<ol>
<li><strong>解耦对象创建和使用</strong>:客户端只需关注接口,无需关心具体实现。</li>
<li><strong>符合开闭原则</strong>:工厂方法模式中,新增产品只需扩展工厂子类。</li>
<li><strong>便于维护和扩展</strong>:创建逻辑集中,修改时只需调整工厂类。</li>
<li><strong>利于代码复用</strong>:工厂类可被多个客户端复用。</li>
</ol>
<ul>
<li><strong>缺点</strong></li>
</ul>
<ol>
<li><strong>类数量增加</strong>:每个产品都可能需要对应的工厂类,导致代码结构复杂。</li>
<li><strong>抽象层级提高</strong>:需要理解抽象工厂和具体工厂的关系,增加学习成本。</li>
<li><strong>过度设计风险</strong>:简单场景下使用工厂模式可能增加不必要的复杂度。</li>
</ol>
<h3 id="什么场景下使用工厂模式">什么场景下使用工厂模式</h3>
<ol>
<li><strong>对复杂对象的创建</strong>:某些类在new创建完之后,并不能拥有完成的功能,需要一些参数,活在构造方法中有复杂的参数传递时,这个时候就需要用到工厂模式</li>
<li><strong>根据条件动态创建对象</strong>:在支付的场景下,可能有微信、支付宝、银联等多种支付方式,可以根据选择创建不同的对象</li>
<li><strong>统一管理对象创建逻辑</strong>:以spring为例,在bean的实例化过程中,需要统一管理bean的生命周期,涉及一整套的接口判断,逻辑校验等,这个时候也可以是工厂模式</li>
</ol>
<h3 id="代码举例">代码举例</h3>
<p>下边以简单工厂模式、工厂方法、抽象工厂、实例开发中怎么用举例。(这里仅仅是一个设计思路,实际开发中还需要根据功能和业务修改)</p>
<ol>
<li>
<p><strong>简单工厂</strong>:</p>
<p>举例一个实际开发中用的场景,用户上传文件,但是文件涉及多种,比如flat文件、Excel、json、xml文件,上传的文件读取内容,下边就用工厂模式来设计</p>
<pre><code class="language-java">interface FileItemReader&lt;T&gt;{
    List&lt;T&gt; read();
}
   
class FlatFileItemReader&lt;T&gt; implements FileItemReader&lt;T&gt;{
@Override
public List&lt;T&gt; read() {
    return null;
}
}

class ExcelItemReader&lt;T&gt; implements FileItemReader&lt;T&gt;{
@Override
public List&lt;T&gt; read() {
    return null;
}
}

class JsonFileItemReader&lt;T&gt; implements FileItemReader&lt;T&gt;{
@Override
public List&lt;T&gt; read() {
    return null;
}
}

class FileItemReaderFactory&lt;T&gt;{
public FileItemReader&lt;T&gt; createFileItemReader(String fileName){
    if(fileName.endsWith("csv") || fileName.endsWith("txt")){
      return new FlatFileItemReader&lt;&gt;();
    }else if(fileName.endsWith("xlsx") || fileName.endsWith("xls")){
      return new ExcelItemReader&lt;&gt;();
    }else if(fileName.endsWith("json")){
      return new JsonFileItemReader&lt;&gt;();
    }else {
      throw new IllegalArgumentException("不支持的文件类型");
    }
}
}

public class FactoryDemo {

    public static void main(String[] args) {
      String fileName = "test.xlsx";
      FileItemReaderFactory&lt;ReadTestEntity&gt; factory = new FileItemReaderFactory&lt;&gt;();
      FileItemReader&lt;ReadTestEntity&gt; fileItemReader = factory.createFileItemReader(fileName);
      List&lt;ReadTestEntity&gt; read = fileItemReader.read();
    }
}
</code></pre>
</li>
<li>
<p><strong>工厂方法</strong>:</p>
<p>以读数据为例子,读数据可能从数据库里读、文件里读、还有一些非关系型数据库中读,就用工厂方法设计下边程序,就用上边的例子继续拓展了</p>
<pre><code class="language-java">interface ItemReader&lt;T&gt; {
List&lt;T&gt; read();
}

interface FileItemReader&lt;T&gt; extends ItemReader&lt;T&gt; {

}

class FlatFileItemReader&lt;T&gt; implements FileItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

class ExcelItemReader&lt;T&gt; implements FileItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

class JsonFileItemReader&lt;T&gt; implements FileItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

interface JdbcItemReader&lt;T&gt; extends ItemReader&lt;T&gt; {

}

class JdbcCursorItemReader&lt;T&gt; implements JdbcItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

class HibernateItemReader&lt;T&gt; implements JdbcItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

interface Creator&lt;T&gt; {
ItemReader&lt;T&gt; create(String type);
}

class FileItemReaderFactory&lt;T&gt; implements Creator&lt;T&gt; {
@Override
public ItemReader&lt;T&gt; create(String fileName) {
    if (fileName.endsWith("csv") || fileName.endsWith("txt")) {
      return new FlatFileItemReader&lt;&gt;();
    } else if (fileName.endsWith("xlsx") || fileName.endsWith("xls")) {
      return new ExcelItemReader&lt;&gt;();
    } else if (fileName.endsWith("json")) {
      return new JsonFileItemReader&lt;&gt;();
    } else {
      throw new IllegalArgumentException("不支持的文件类型");
    }
}
}

class JdbcItemReaderFactory&lt;T&gt; implements Creator&lt;T&gt; {
@Override
public ItemReader&lt;T&gt; create(String type) {
    if(type.equals("jdbc")){
      return new JdbcCursorItemReader&lt;&gt;();
    }else if (type.equals("hibernate")){
      return new HibernateItemReader&lt;&gt;();
    }else {
      throw new IllegalArgumentException("不支持的文件类型");
    }
}
}

public static void main(String[] args) {
      String fileName = "test.xlsx";
      Creator&lt;ReadTestEntity&gt; creator = new FileItemReaderFactory&lt;&gt;();
      List&lt;ReadTestEntity&gt; read = creator.create(fileName).read();
}
</code></pre>
</li>
<li>
<p><strong>抽象工厂</strong></p>
<p>继续上边的设计,以读取flat类型文件为例,读取文件时候需要获取不同的流,也需要不同的数据映射关系,这里用抽象工厂就很合适</p>
<pre><code class="language-java">interface ItemReader&lt;T&gt; {
List&lt;T&gt; read();
}

interface FileItemReader&lt;T&gt; extends ItemReader&lt;T&gt; {

}

class FlatFileItemReader&lt;T&gt; implements FileItemReader&lt;T&gt; {

private final BufferReaderFactory bufferReaderFactory;
private final BeanMappingFactory beanMappingFactory;

public FlatFileItemReader(BufferReaderFactory bufferReaderFactory, BeanMappingFactory beanMappingFactory) {
    this.bufferReaderFactory = bufferReaderFactory;
    this.beanMappingFactory = beanMappingFactory;
}


@Override
public List&lt;T&gt; read() {
    return null;
}
}

class ExcelItemReader&lt;T&gt; implements FileItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

class JsonFileItemReader&lt;T&gt; implements FileItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

interface JdbcItemReader&lt;T&gt; extends ItemReader&lt;T&gt; {

}

class JdbcCursorItemReader&lt;T&gt; implements JdbcItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

class HibernateItemReader&lt;T&gt; implements JdbcItemReader&lt;T&gt; {
@Override
public List&lt;T&gt; read() {
    return null;
}
}

interface Creator&lt;T&gt; {
ItemReader&lt;T&gt; create(String type);
}

class FileItemReaderFactory&lt;T&gt; implements Creator&lt;T&gt; {
private final BufferReaderFactory bufferReaderFactory;
private final BeanMappingFactory beanMappingFactory;

public FileItemReaderFactory(BufferReaderFactory bufferReaderFactory, BeanMappingFactory beanMappingFactory) {
    this.bufferReaderFactory = bufferReaderFactory;
    this.beanMappingFactory = beanMappingFactory;
}

@Override
public ItemReader&lt;T&gt; create(String fileName) {
    if (fileName.endsWith("csv") || fileName.endsWith("txt")) {
      return new FlatFileItemReader&lt;&gt;(bufferReaderFactory, beanMappingFactory);
    } else if (fileName.endsWith("xlsx") || fileName.endsWith("xls")) {
      return new ExcelItemReader&lt;&gt;();
    } else if (fileName.endsWith("json")) {
      return new JsonFileItemReader&lt;&gt;();
    } else {
      throw new IllegalArgumentException("不支持的数据库读取类型");
    }
}
}

class JdbcItemReaderFactory&lt;T&gt; implements Creator&lt;T&gt; {
@Override
public ItemReader&lt;T&gt; create(String type) {
    if(type.equals("jdbc")){
      return new JdbcCursorItemReader&lt;&gt;();
    }else if (type.equals("hibernate")){
      return new HibernateItemReader&lt;&gt;();
    }else {
      throw new IllegalArgumentException("不支持的数据库读取类型");
    }
}
}

interface BufferReaderFactory {
BufferedReader create(Resource resource, String encoding);
}

interface BeanMappingFactory {
BeanPropertyMap create(Class&lt;?&gt; clazz, String lineData);
}
   
public static void main(String[] args) {
      String fileName = "test.xlsx";
      Creator&lt;ReadTestEntity&gt; creator = new FileItemReaderFactory&lt;&gt;();
      List&lt;ReadTestEntity&gt; read = creator.create(fileName).read();
}
</code></pre>
</li>
</ol>
<h3 id="总结">总结</h3>
<p>通过上边的举例,工厂模式其实就是将较为复杂的类创建,统一的bean的生命周期,不同类型的类统一封装起来,为了代码的解偶。</p><br><br>
来源:https://www.cnblogs.com/MaC-Matthew/p/18941089
頁: [1]
查看完整版本: 设计模式-工厂模式