【Java设计模式 | 创建者模式】工厂方法模式

前言:

创建者模式主要关注是"怎么创建对象?",它的主要特点是将对象的创建和使用分离。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。

创建者模式分为:

单例模式(Singleton): 【Java设计模式 | 创建者模式】单例模式-CSDN博客

工厂方法模式(Factory Method):【Java设计模式 | 创建者模式】工厂方法模式-CSDN博客

抽象工厂模式(Abstract Factory)

建造者模式(Builder)

原型模式(Prototype)

在Java中,万物皆对象,这些对象都需要创建,如果都是用new来创建该对象,就会对该对象耦合严重,假如我们要更换对象,所有new对象的地方都需要去修改,这显然违背了软件设计的开闭原则。如果我们我们使用工厂来生产对象,就可以只和工厂打交道,实现对对象的解耦。所以说工厂模式最大的优点就是:解耦。

简单工厂模式(并不属于GOF的23种经典模式):

结构:

简单工厂模式包含如下角色:

**产品接口:**定义了产品的规范,描述了产品的主要特性和功能。

**具体产品:**实现或者继承抽象产品的子类。

**具体工厂:**提供了创建产品的方法,调用者通过该方法来创建产品。

实现:

  1. 产品接口定义了所有产品共有的方法display()
  2. 具体产品类ConcreteProductAConcreteProductB实现了产品接口
  3. 工厂类SimpleFactory包含静态方法createProduct(),根据输入参数创建不同类型的产品对象
  4. 客户端代码通过调用工厂方法获取产品实例,无需直接实例化具体产品类
java 复制代码
// 定义产品接口
interface Product {
    void display();
}

// 具体产品类A
class ConcreteProductA implements Product {
    @Override
    public void display() {
        System.out.println("This is Product A");
    }
}

// 具体产品类B
class ConcreteProductB implements Product {
    @Override
    public void display() {
        System.out.println("This is Product B");
    }
}

// 简单工厂类
class SimpleFactory {
    public Product createProduct(String type) {
        if (type.equalsIgnoreCase("A")) {
            return new ConcreteProductA();
        } else if (type.equalsIgnoreCase("B")) {
            return new ConcreteProductB();
        }
        throw new IllegalArgumentException("Unknown product type");
    }
}

// 客户端代码
public class FactoryPatternDemo {
    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.display();

        Product productB = SimpleFactory.createProduct("B");
        productB.display();
    }
}
 

优点:

封装了创建对象的过程,可以通过参数创建对应的对象。把对象的创建和业务逻辑层分开,这样就降低了修改客户端代码的可能性。

缺点:

如果后期需要添加产品"C",还是需要修改工厂中的代码,产生了新的耦合,还是违背了开闭原则。

静态工厂模式(并不属于GOF的23种经典模式):

与简单工厂模式唯一不同的就是创建产品的方法使用static修饰。

java 复制代码
// 简单工厂类
class SimpleFactory {
    public static Product createProduct(String type) {
        if (type.equalsIgnoreCase("A")) {
            return new ConcreteProductA();
        } else if (type.equalsIgnoreCase("B")) {
            return new ConcreteProductB();
        }
        throw new IllegalArgumentException("Unknown product type");
    }
}

 

工厂方法模式:

针对简单工厂模式和静态工厂模式的弊端,我们选择引入工厂方法模式来解决,工厂方法模式完全遵循了开闭原则。

概念:

定义一个用于创建对象的接口,让子类决定实例化哪个产品对象。工厂方法使一个产品类的实例化延迟到其工厂的子类。

结构:

工厂方法模式的主要角色:

**抽象工厂(Abstract Factory):**提供了创建产品的接口,调用者通过它访问的具体工厂的工厂方法来创建产品。

**具体工厂(ConcreteFactory):**主要是实现抽象工厂中的抽象方法,完成了具体产品的创建。

**产品接口(Product):**定义了产品的规范,描述了产品的主要特性和功能。

**具体产品(ConcreteProduct):**实现了抽象产品角色所定义的接口,由具体工厂来创建。它同具体工厂之间一一对应。

实现:

java 复制代码
//抽象产品接口(Product)
public interface Product {
    void operation();
}


//具体产品类(ConcreteProduct)
public class ConcreteProductA implements Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductA operation");
    }
}

public class ConcreteProductB implements Product {
    @Override
    public void operation() {
        System.out.println("ConcreteProductB operation");
    }
}

//抽象工厂类(Abstract Factory)
public abstract class AbstractFactory {
    public abstract Product createProduct();
}

//具体工厂类(Concrete Factory)
public class ConcreteFactoryA extends AbstractFactory {
    @Override
    public Product createProduct() {
        return new ConcreteProductA();
    }
}

public class ConcreteFactoryB extends AbstractFactory {
    @Override
    public Product createProduct() {
        return new ConcreteProductB();
    }
}

//客户端代码示例
public class Client {
    public static void main(String[] args) {
        AbstractFactory factoryA = new ConcreteFactoryA();
        Product productA = factoryA.createProduct();
        productA.operation();

        AbstractFactory factoryB = new ConcreteFactoryB();
        Product productB = factoryB.createProduct();
        productB.operation();
    }
}
//输出结果
ConcreteProductA operation
ConcreteProductB operation

优点:

用户只需要知道具体工厂的名称即可创建对应的产品,无需知道产品的创建过程;

在系统增加新的产品时只需要添加对应的具体产品类和具体工厂类即可,无需对原工厂类进行任何修改,满足开闭原则。

缺点:

每增加一个产品就需要添加对应的具体产品类和具体工厂类,写起来更繁琐。

相关推荐
白晨并不是很能熬夜13 分钟前
【PRC】第 2 篇:Netty 通信层 — NIO 模型 + 自定义协议 + 心跳
java·开发语言·后端·面试·rpc·php·nio
斯普润布特26 分钟前
物联网-Spring+Netty 框架整合
java·物联网·netty
简简单单就是我_hehe27 分钟前
后端链路追踪局部采集和全量采集配置说明
java·开发语言
zshs00028 分钟前
#从偶发无字幕到补偿探测链路:一次 B 站字幕导入问题的完整收敛过程
java·后端·重构
存在的五月雨44 分钟前
SpringBoot 基于数据库的动态定时任务管理器实现方案
java·spring boot
IT_陈寒1 小时前
JavaScript里这个隐式类型转换的坑,我终于爬出来了
前端·人工智能·后端
掘金者阿豪1 小时前
Django接金仓数据库:我踩过的坑和填坑指南
后端
椰羊~王小美1 小时前
@RequestMapping注解的各个属性作用
java
_风满楼1 小时前
HTTP 请求的五种传参方式
前端·javascript·后端
码事漫谈2 小时前
为什么 token 计费规则里,输出比输入贵那么多
后端