工厂模式(Factory)

简介: 工厂模式是创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,创建对象不会对客户端暴露创建逻辑,隐藏创建对象的详情,从而实现客户端与具体实现的解耦。工厂模式设计时需求注意的点:工厂类提供公共的方法来创建对象,无论静态,而不是客户端直接创建方法的参数可选,但参数只用来决定哪种实现,不应该存在业务参数方法的返回一般是被创建的接口对象,也可以是抽象类或具体类常见的工厂模式有工厂方法模式、简单工厂模式和抽象工厂模式等,并不要拘泥于哪种,在实际业务中根据需求设计。


一、概述



工厂模式是创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,创建对象不会对客户端暴露创建逻辑,隐藏创建对象的详情,从而实现客户端与具体实现的解耦。工厂模式设计时需求注意的点:

  • 工厂类提供公共的方法来创建对象,无论静态,而不是客户端直接创建
  • 方法的参数可选,但参数只用来决定哪种实现,不应该存在业务参数
  • 方法的返回一般是被创建的接口对象,也可以是抽象类或具体类

常见的工厂模式有工厂方法模式、简单工厂模式和抽象工厂模式等,并不要拘泥于哪种,在实际业务中根据需求设计。


二、工厂方法



工厂方法模式(Factory Method)定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实例化延迟到其子类。在代码中,使用不同的工厂子类创建不同的对象,创建对象的细节封装在子类中。比如我们使用工厂方法来实现绘制不同形状的图形。

微信图片0001.jpg

定义一个 Shape 接口,并添加实现类,编写示例代码如下:

// Shape.java
public interface Shape {
    void draw();
}
// Circle.java
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Circle.draw");
    }
}
// Rectangle.java
public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Rectangle.draw");
    }
}
// Square.java
public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Square.draw");
    }
}

针对 Shape 接口定义一个抽象工厂类 ShapeFactory,并添加各个实例类的工厂子类,编写代码如下:

// ShapeFactory.java
public abstract class ShapeFactory {
    public void operate() {
        Shape shape = factoryMethod();
        shape.draw();
    }
    // 将创建对象的细节交给子类
    protected abstract Shape factoryMethod();
}
// CircleFactory.java
public class CircleFactory extends ShapeFactory {
    @Override
    protected Shape factoryMethod() {
        return new Circle();
    }
}
// RectangleFactory.java
public class RectangleFactory extends ShapeFactory {
    @Override
    protected Shape factoryMethod() {
        return new Rectangle();
    }
}
// SquareFactory.java
public class SquareFactory extends ShapeFactory {
    @Override
    protected Shape factoryMethod() {
        return new Square();
    }
}

编写主方法类,运行示例代码:

// Main.java
public class Main {
    public static void main(String[] args) {
        new CircleFactory().operate();
        new RectangleFactory().operate();
        new SquareFactory().operate();
    }
}


三、简单工厂



简单工厂模式(Factory)定义用于创建对象的类,客户端调用工厂类方法(静态或非静态)根据参数类型创建不同的对象实例,从而使得客户端和实现之间解耦。比如我们使用简单静态工厂来绘制不同形状的图形。

微信图片0002.png

定义一个工厂类,添加静态方法来根据类型创建不同实例,编写代码如下:

public class ShapeFactory {
    public static Shape getShape(String shapeType) {
        if ("CIRCLE".equalsIgnoreCase(shapeType)) {
            return new Circle();
        }
        if ("RECTANGLE".equalsIgnoreCase(shapeType)) {
            return new Rectangle();
        }
        if ("SQUARE".equalsIgnoreCase(shapeType)) {
            return new Square();
        }
        return null;
    }
}

编写主方法类,运行示例代码:

public class Main {
    public static void main(String[] args) {
        Shape circle = ShapeFactory.getShape("CIRCLE");
        circle.draw();
        Shape rectangle = ShapeFactory.getShape("RECTANGLE");
        rectangle.draw();
        Shape square = ShapeFactory.getShape("SQUARE");
        square.draw();
    }
}

简单工厂与工厂方法不一样的地方是简单工厂是客户端根据方法的参数类型来创建不同的对象。参数类型可以是整型数据、字符串等基本数据类型,也可以是枚举或其他类型,只要可以区分创建对象的实例类型就行,我们也可以利用环境配置,或者某个 Profile 来确定创建的对象实例,以达到兼容的目的。


四、抽象工厂



微信图片0003.png

抽象工厂模式(Abstract Factory)和工厂模式很相似,抽象工厂对工厂类进行了一层抽象,抽象的工厂类(超级工厂)可以创建其他工厂。比如我们基于前面的例子绘制不同形状的图形,并且给图形填充不同的颜色

定义一个 Color 颜色接口,并添加实现类,编写示例代码如下:

// Color.java
public interface Color {
    void fill();
}
// Red.java
public class Red implements Color {
    @Override
    public void fill() {
        System.out.println("Red.fill");
    }
}
// Green.java
public class Green implements Color {
    @Override
    public void fill() {
        System.out.println("Green.fill");
    }
}
// Blue.java
public class Blue implements Color {
    @Override
    public void fill() {
        System.out.println("Blue.fill");
    }
}

定义一个抽象工厂,并添加形状和颜色的实现工厂类,编写代码如下:

// AbstractFactory.java
public abstract class AbstractFactory {
    public abstract Color getColor(String color);
    public abstract Shape getShape(String shape);
}
// ShapeFactory.java
public class ShapeFactory extends AbstractFactory {
    @Override
    public Shape getShape(String shape) {
        if ("CIRCLE".equalsIgnoreCase(shape)) {
            return new Circle();
        } else if ("RECTANGLE".equalsIgnoreCase(shape)) {
            return new Rectangle();
        } else if ("SQUARE".equalsIgnoreCase(shape)) {
            return new Square();
        }
        return null;
    }
    @Override
    public Color getColor(String color) {
        return null;
    }
}
// ColorFactory.java
public class ColorFactory extends AbstractFactory {
    @Override
    public Color getColor(String color) {
        if ("RED".equalsIgnoreCase(color)) {
            return new Red();
        } else if ("GREEN".equalsIgnoreCase(color)) {
            return new Green();
        } else if ("BLUE".equalsIgnoreCase(color)) {
            return new Blue();
        }
        return null;
    }
    @Override
    public Shape getShape(String shape) {
        return null;
    }
}

定义超级工厂类,用于生产工厂类,编写代码如下:

// FactoryProducer.java
public class FactoryProducer {
    public static AbstractFactory getFactory(String choice) {
        if ("SHAPE".equalsIgnoreCase(choice)) {
            return new ShapeFactory();
        } else if ("COLOR".equalsIgnoreCase(choice)) {
            return new ColorFactory();
        }
        return null;
    }
}

编写主方法类,运行示例代码

// Main.java
public class Main {
    public static void main(String[] args) {
        AbstractFactory shapeFactory = FactoryProducer.getFactory("SHAPE");
        Shape shape;
        shape = shapeFactory.getShape("CIRCLE");
        shape.draw();
        shape = shapeFactory.getShape("RECTANGLE");
        shape.draw();
        shape = shapeFactory.getShape("SQUARE");
        shape.draw();
        AbstractFactory colorFactory = FactoryProducer.getFactory("COLOR");
        Color color;
        color = colorFactory.getColor("RED");
        color.fill();
        color = colorFactory.getColor("GREEN");
        color.fill();
        color = colorFactory.getColor("BLUE");
        color.fill();
    }
}

抽象工厂模式基于简单工厂模式又对工厂进行了一层抽象,将工厂类也以工厂的形式创建。


五、Spring实现工厂



Spring容器管理一个接口的多个实现类Bean时,可以使用 Map 形式注入所有实现类的Bean,这个Map的Key为注册Bean的BeanName,Map的Value为对应的Bean。所以我们可以利用这个特性使用Spring的IoC功能实现一个工厂模式,还是使用前面的示例。

Spring 默认注册的 BeanName 一般为类名的小驼峰形式,也可以自己指定。

定义一个 Shape 接口,并添加实现类,此时所有的实现类交给Spring管理,编写代码如下:

// Shape.java
public interface Shape {
    void draw();
}
// Circle.java
@Service
public class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("Circle.draw");
    }
}
// Rectangle.java
@Service
public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Rectangle.draw");
    }
}
// Square.java
@Service
public class Square implements Shape {
    @Override
    public void draw() {
        System.out.println("Square.draw");
    }
}




定义一个工厂类,也要交给Spring管理,然后使用 Map 注入需要生产的Bean,编写代码如下:

// ShapeFactory.java
@Service
public class ShapeFactory {
    private static Map<String, Shape> shapeMap;
    public static Shape getShape(String beanName) {
        return shapeMap.get(beanName);
    }
    @Autowired
    public void setShapeMap(Map<String, Shape> shapeMap) {
        ShapeFactory.shapeMap = shapeMap;
    }
}

编写主方法类,定义ApplicationContext并扫描前面注册Bean所在的包,编写代码如下:

// Main.java
public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext("com.ajn.spring.factory");
        Shape circle = ShapeFactory.getShape("circle");
        circle.draw();
        Shape rectangle = ShapeFactory.getShape("rectangle");
        rectangle.draw();
        Shape square = ShapeFactory.getShape("square");
        square.draw();
    }
}


目录
相关文章
|
测试技术 C语言 Perl
内存优化-使用tcmalloc分析解决内存泄漏和内存暴涨问题
其实我一直很想写关于tcmalloc的内存泄漏检测的文章,只是一直记不起来该如何下笔,有时项目太忙,在整理这方便的思考过少,另外遇到的问题也不是很多,直到最近用tcmalloc帮A项目排查...
|
11月前
|
机器学习/深度学习 人工智能 物联网
通义灵码在人工智能与机器学习领域的应用
通义灵码不仅在物联网领域表现出色,还在人工智能、机器学习、金融、医疗和教育等领域展现出广泛应用前景。本文探讨了其在这些领域的具体应用,如模型训练、风险评估、医疗影像诊断等,并总结了其提高开发效率、降低门槛、促进合作和推动创新的优势。
通义灵码在人工智能与机器学习领域的应用
|
7月前
|
缓存 Java 数据库
微服务——SpringBoot使用归纳——Spring Boot中使用监听器——监听器介绍和使用
本文介绍了在Spring Boot中使用监听器的方法。首先讲解了Web监听器的概念,即通过监听特定事件(如ServletContext、HttpSession和ServletRequest的创建与销毁)实现监控和处理逻辑。接着详细说明了三种实际应用场景:1) 监听Servlet上下文对象以初始化缓存数据;2) 监听HTTP会话Session对象统计在线用户数;3) 监听客户端请求的Servlet Request对象获取访问信息。每种场景均配有代码示例,帮助开发者理解并应用监听器功能。
493 0
|
11月前
|
算法
基于HASM模型的高精度建模matlab仿真
本课题使用HASM进行高精度建模,介绍HASM模型及其简化实现方法。HASM模型基于层次化与自适应统计思想,通过多层结构捕捉不同尺度特征,自适应调整参数,适用于大规模、高维度数据的分析与预测。MATLAB2022A版本运行测试,展示运行结果。
|
5月前
|
设计模式 数据采集 算法
【设计模式】【行为型模式】模板方法模式(Template Method)
一、入门 1.1、什么是模板方法模式? 模板模式(Template Method Pattern)是一种行为设计模式,它定义了一个算法的框架,并允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
189 13
|
7月前
|
Java Spring
SpringBoot自动配置原理
本文深入解析了SpringBoot的核心功能——自动配置,重点探讨了`org.springframework.boot.autoconfigure`及相关注解的工作机制。通过分析`@SpringBootApplication`、`@EnableAutoConfiguration`等注解,揭示了SpringBoot如何基于类路径和条件自动装配Bean
385 7
|
7月前
|
Java
SpringBoot自动装配的原理
在SpringBoot项目的启动引导类上都有一个注解@SpringBootApplication 这个注解是一个复合注解, 其中有三个注解构成 , 分别是 ● @SpringBootConfiguration : 是@Configuration的派生注解 , 标注当前类是一个SpringBoot的配置类 ● @ComponentScan : 开启组件扫描, 默认扫描的是当前启动引导了所在包以及子包 ● @EnableAutoConfiguration : 开启自动配置(自动配置核心注解) 2.在@EnableAutoConfiguration注解的内容使用@Import注解导入了一个AutoC
|
监控 大数据 Java
使用Apache Flink进行大数据实时流处理
Apache Flink是开源流处理框架,擅长低延迟、高吞吐量实时数据流处理。本文深入解析Flink的核心概念、架构(包括客户端、作业管理器、任务管理器和数据源/接收器)和事件时间、窗口、状态管理等特性。通过实战代码展示Flink在词频统计中的应用,讨论其实战挑战与优化。Flink作为大数据处理的关键组件,将持续影响实时处理领域。
1877 5
|
设计模式 Java Spring
Spring Boot监听器的底层实现原理
Spring Boot监听器的底层实现原理主要基于观察者模式(也称为发布-订阅模式),这是设计模式中用于实现对象之间一对多依赖的一种常见方式。在Spring Boot中,监听器的实现依赖于Spring框架提供的事件监听机制。
306 1
|
NoSQL MongoDB 数据库
【MongoDB 专栏】MongoDB 的并发控制与锁机制
【5月更文挑战第11天】MongoDB的并发控制和锁机制保证数据一致性和性能。全局锁用于特殊情况如数据库初始化,限制并发性能;文档级锁提供更高的并发性,针对单个文档锁定。乐观并发控制利用版本号检查减少锁竞争。在分布式环境下,需协调多节点锁,优化包括合理设计数据模型、调整锁配置和利用分布式事务。未来,MongoDB将持续改进这些机制以应对复杂需求。了解并发控制原理对于数据库开发者至关重要。
595 2
【MongoDB 专栏】MongoDB 的并发控制与锁机制