Java设计模式—工厂模式

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS AI 助手,专业版
简介: Java设计模式—工厂模式

工厂模式主要是为创建对象提供了接口。工厂模式分为三类:1. 简单工厂模式(Simple Factory) 2. 工厂方法模式(Factory Method) 3. 抽象工厂模式(Abstract Factory)


三个设计模式名字中都含有“工厂”二字,其含义是使用工厂(一个或一系列方法)去生产产品(一个或一系列类的实例)。


另外,有时候,我们常常会将生产产品的一个或一系列方法封装到一个类中,我习惯把这个类叫做“工厂类”;而被实例化的类称作“产品类”。


下面是使用工厂模式的两种情况:1.在编码时不能预见需要创建哪种类的实例。2.系统不应依赖于产品类实例如何被创建、组合和表达的细节。


一:Simple Factory


简单工厂模式:工厂类(SimpleFactory)拥有一个工厂方法(create),接受了一个参数,通过不同的参数实例化不同的产品类。


有4个角色


工厂类角色:是具体产品类角色直接调用者。

抽象产品角色:接口或抽象类,负责具体产品角色的定义,及与客户端的交互。

具体产品角色:被工厂类创建的对象,也是客户端实际操作对象。

客户端:调用工厂类产生实例,并调用实例的方法进行相应工作。

a9c94dd2c38cb861a872f1688750491b.png

抽象产品接口

package cn.design.factory;
public interface DBDriver {
    public void dbConn(String ip);
    public void dbClose();
    public String dbOper();
}

View Code

具体产品接口:

package cn.design.factory;
public class MySqlDriver implements DBDriver{
    @Override
    public void dbConn(String ip) {
        // TODO Auto-generated method stub
        System.out.println("已成功连接到MySql数据库! 数据库地址为"+ip);
    }
    @Override
    public void dbClose() {
        // TODO Auto-generated method stub
        System.out.println("MySql数据库连接已关闭!");
    }
    @Override
    public String dbOper() {
        // TODO Auto-generated method stub
        String s="正在对MySql数据库进行操作";
        System.out.println("正在对MySql数据库进行操作");
        return s;
    }
}

View Code

package cn.design.factory;
public class OracleDriver implements DBDriver{
    @Override
    public void dbConn(String ip) {
        // TODO Auto-generated method stub
        System.out.println("已连接到Oracle数据库 数据库地址为 "+ip);
    }
    @Override
    public void dbClose() {
        // TODO Auto-generated method stub
        System.out.println("已关闭Oracle数据库连接");
    }
    @Override
    public String dbOper() {
        // TODO Auto-generated method stub
        String s="正在对Oracle数据库进行操作";
        System.out.println("正在对Oracle数据库进行操作");
        return s;
    }
}

View Code

package cn.design.factory;
public class DB2Driver implements DBDriver{
    @Override
    public void dbConn(String ip) {
        // TODO Auto-generated method stub
        System.out.println("准备连接DB2数据库: ip地址为:"+ ip);
    }
    @Override
    public void dbClose() {
        // TODO Auto-generated method stub
        System.out.println("关闭DB2链接");
    }
    @Override
    public String dbOper() {
        // TODO Auto-generated method stub
        System.out.println("正在对DB2数据库进行操作");
        return null;
    }
}

View Code

工厂类:

package cn.design.factory;
/**
 * 联想到之前写过的多态相关代码
 * 继承关系
 * 重写父类的方法
 * 父类引用指向子类对象
 * @author 翎野君
 *
 */
public class SimpleFactory {
    public static DBDriver getDBDriver(String dbType){
        switch(dbType){
        case "oracle":
            return new OracleDriver();
        case "mysql":
            return new MySqlDriver();
        case "db2":
            return new DB2Driver();
        default:
            return new MySqlDriver();
        }
    }
    public static void main(String[] args) {
        DBDriver db=SimpleFactory.getDBDriver("db2");
        db.dbConn("127.0.0.1");
        db.dbOper();
        db.dbClose();
    }
}

View Code

优点:


   (1)很明显,简单工厂的特点就是“简单粗暴”,通过一个含参的工厂方法,我们可以实例化任何产品类,上至飞机火箭,下至土豆面条,无所不能。所以简单工厂有一个别名:上帝类。


缺点:


   (1)任何”东西“的子类都可以被生产,负担太重。当所要生产产品种类非常多时,工厂方法的代码量可能会很庞大。


   (2)在遵循开闭原则(对拓展开放,对修改关闭)的条件下,简单工厂对于增加新的产品,无能为力。因为增加新产品只能通过修改工厂方法来实现。


二:Factory Method


工厂方法是针对每一种产品提供一个工厂类。通过不同的工厂实例来创建不同的产品实例。

工厂方法解决了上述简单工厂上述的两个缺点。

工厂方法由一下四部分组成:


1、抽象工厂角色:这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类。在java中它由抽象类或者接口来实现。


2、具体工厂角色:它含有和具体业务逻辑有关的代码。由应用程序调用以创建对应的具体产品的对象。在java中它由具体的类来实现。


3、抽象产品角色:它是具体产品继承的父类或者是实现的接口。在java中一般有抽象类或者接口来实现。


4、具体产品角色:具体工厂角色所创建的对象就是此角色的实例。在java中由具体的类来实现。

35a6c27851091017441e39b14dff372a.png

首先完全实现‘开-闭 原则’,实现了可扩展。其次更复杂的层次结构,可以应用于产品结果复杂的场合。

package cn.design.factory;
public class FactoryMethod{
    /**
     * 工厂模式最后对外开放给使用者的就是一个一个的工厂类(Factory)
     */
    public static void main(String[] args) {
        MysqlFactory mf=new MysqlFactory();
        OracleFactory of=new OracleFactory();
        mf.getDBConn().getDriver();
        mf.getDBConn().getUrl();
        mf.getDBConn().getUP();
        mf.getDBConn().connDB();
        of.getDBConn().getDriver();
        of.getDBConn().getUrl();
        of.getDBConn().getUP();
        of.getDBConn().connDB();
    }
}
/**
 * 抽象的数据库连接角色
 * @author 翎野君
 *
 */
interface ConnDBInterface{
    public void getDriver();
    public void getUrl();
    public void getUP();
    public void connDB();
}
/**
 * 抽象工厂角色
 * @author 翎野君
 *
 */
interface FactoryMethodInterface{
    public ConnDBInterface getDBConn();
}
/**
 * 专门连接Mysql的工厂
 * @author 翎野君
 *
 */
class MysqlFactory implements FactoryMethodInterface{
    @Override
    public ConnDBInterface getDBConn() {
        // TODO Auto-generated method stub
        return new ConnMysql();
    }
}
/**
 * 专门连接Oracle的工厂
 */
class OracleFactory implements FactoryMethodInterface{
    @Override
    public ConnDBInterface getDBConn() {
        // TODO Auto-generated method stub
        return new ConnOracle();
    }
}
/**
 * 具体的连接Mysql的实现类
 * @author 翎野君
 *
 */
class ConnMysql implements ConnDBInterface{
    @Override
    public void getDriver() {
        // TODO Auto-generated method stub
        System.out.println("加载mysql数据库驱动");
    }
    @Override
    public void getUrl() {
        // TODO Auto-generated method stub
        System.out.println("获取mysql连接地址127.0.0.1");
    }
    @Override
    public void getUP() {
        // TODO Auto-generated method stub
        System.out.println("获取mysql的用户名:root 密码:password");
    }
    @Override
    public void connDB() {
        // TODO Auto-generated method stub
        System.out.println("成功连接到mysql数据库");
    }
}
/**
 * 具体的连接Oracle的实现类
 * @author 翎野君
 *
 */
class ConnOracle implements ConnDBInterface{
    @Override
    public void getDriver() {
        // TODO Auto-generated method stub
        System.out.println("加载oracle数据库驱动");
    }
    @Override
    public void getUrl() {
        // TODO Auto-generated method stub
        System.out.println("获取oracle连接地址127.0.0.1");
    }
    @Override
    public void getUP() {
        // TODO Auto-generated method stub
        System.out.println("获取oracle的用户名:root 密码:password");
    }
    @Override
    public void connDB() {
        // TODO Auto-generated method stub
        System.out.println("成功连接到oracle数据库");
    }
}

View Code

优点:


   (1)工厂方法模式就很好的减轻了工厂类的负担,把某一类/某一种东西交由一个工厂生产;(对应简单工厂的缺点1)


   (2)同时增加某一类”东西“并不需要修改工厂类,只需要添加生产这类”东西“的工厂即可,使得工厂类符合开放-封闭原则。


缺点:


   (1)相比简单工厂,实现略复杂。


   (2)对于某些可以形成产品族的情况处理比较复杂。


 对于缺点(2),我们可以借用抽象工厂来实现。


三:Abstract Factory


抽象工厂是应对产品族概念的


 例如,汽车可以分为轿车、SUV、MPV等,也分为奔驰、宝马等。我们可以将奔驰的所有车看作是一个产品族,而将宝马的所有车看作是另一个产品族。分别对应两个工厂,一个是奔驰的工厂,另一个是宝马的工厂。与工厂方法不同,奔驰的工厂不只是生产具体的某一个产品,而是一族产品(奔驰轿车、奔驰SUV、奔驰MPV)。“抽象工厂”的“抽象”指的是就是这个意思。


 上边的工厂方法模式是一种极端情况的抽象工厂模式(即只生产一种产品的抽象工厂模式),而抽象工厂模式可以看成是工厂方法模式的一种推广。


来看看抽象工厂模式的各个角色(和工厂方法的一样)

177ceff1cb94fbac84c8958d8f5b9c47.png

抽象类

package cn.design.factory;
public abstract class AbstractBenz {
    public abstract void start();
    public abstract void run();
    public abstract void stop();
}

View Code

具体类

package cn.design.factory;
public class BenzSport extends AbstractBenz{
    @Override
    public void start() {
        // TODO Auto-generated method stub
        System.out.println("奔驰跑车启动");
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("奔驰跑车行驶");
    }
    @Override
    public void stop() {
        // TODO Auto-generated method stub
        System.out.println("奔驰跑车熄火");
    }
    public void game(){
        System.out.println("纽伯格林赛道比赛!!!");
    }
}

View Code

package cn.design.factory;
public class BenzMpv extends AbstractBenz{
    @Override
    public void start() {
        // TODO Auto-generated method stub
        System.out.println("奔驰保姆车启动");
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("奔驰保姆车行驶");
    }
    @Override
    public void stop() {
        // TODO Auto-generated method stub
        System.out.println("奔驰保姆车熄火");
    }
    public void sleep(){
        System.out.println("在保姆车中睡觉");
    }
}

View Code

抽象工厂类

package cn.design.factory;
public abstract class AbstractFactory {
    public abstract AbstractBenz getBenzSport();
    public abstract AbstractBenz getBenzMpv();
}

View Code

具体工厂类

package cn.design.factory;
public class BenzFactory extends AbstractFactory{
    @Override
    public BenzSport getBenzSport() {
        // TODO Auto-generated method stub
        return new BenzSport();
    }
    @Override
    public BenzMpv getBenzMpv() {
        // TODO Auto-generated method stub
        return new BenzMpv();
    }
    public static void main(String[] args) {
        BenzFactory bf=new BenzFactory();
        bf.getBenzSport().game();
        bf.getBenzMpv().run();
    }
}

View Code

 优点:针对产品族;


 缺点:针对产品族。


 所以,只有对应产品族的情况下,才需要使用抽象工厂模式。


区别

 简单工厂 : 用来生产同一等级结构中的任意产品。(不支持拓展增加产品)


 工厂方法 :用来生产同一等级结构中的固定产品。(支持拓展增加产品)  


 抽象工厂 :用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)  


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
目录
相关文章
|
5月前
|
设计模式 网络协议 数据可视化
Java 设计模式之状态模式:让对象的行为随状态优雅变化
状态模式通过封装对象的状态,使行为随状态变化而改变。以订单为例,将待支付、已支付等状态独立成类,消除冗长条件判断,提升代码可维护性与扩展性,适用于状态多、转换复杂的场景。
786 157
|
5月前
|
设计模式 Java Spring
Java 设计模式之责任链模式:优雅处理请求的艺术
责任链模式通过构建处理者链,使请求沿链传递直至被处理,实现发送者与接收者的解耦。适用于审批流程、日志处理等多级处理场景,提升系统灵活性与可扩展性。
639 2
|
7月前
|
设计模式 缓存 Java
Java设计模式(二):观察者模式与装饰器模式
本文深入讲解观察者模式与装饰器模式的核心概念及实现方式,涵盖从基础理论到实战应用的全面内容。观察者模式实现对象间松耦合通信,适用于事件通知机制;装饰器模式通过组合方式动态扩展对象功能,避免子类爆炸。文章通过Java示例展示两者在GUI、IO流、Web中间件等场景的应用,并提供常见陷阱与面试高频问题解析,助你写出灵活、可维护的代码。
|
5月前
|
设计模式 算法 搜索推荐
Java 设计模式之策略模式:灵活切换算法的艺术
策略模式通过封装不同算法并实现灵活切换,将算法与使用解耦。以支付为例,微信、支付宝等支付方式作为独立策略,购物车根据选择调用对应支付逻辑,提升代码可维护性与扩展性,避免冗长条件判断,符合开闭原则。
1216 35
|
5月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
475 8
|
10月前
|
设计模式 缓存 安全
【高薪程序员必看】万字长文拆解Java并发编程!(8):设计模式-享元模式设计指南
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的经典对象复用设计模式-享元模式,废话不多说让我们直接开始。
218 0
|
7月前
|
设计模式 安全 Java
Java设计模式(一):单例模式与工厂模式
本文详解单例模式与工厂模式的核心实现及应用,涵盖饿汉式、懒汉式、双重检查锁、工厂方法、抽象工厂等设计模式,并结合数据库连接池与支付系统实战案例,助你掌握设计模式精髓,提升代码专业性与可维护性。
|
7月前
|
设计模式 XML 安全
Java枚举(Enum)与设计模式应用
Java枚举不仅是类型安全的常量,还具备面向对象能力,可添加属性与方法,实现接口。通过枚举能优雅实现单例、策略、状态等设计模式,具备线程安全、序列化安全等特性,是编写高效、安全代码的利器。
|
设计模式 Java 数据安全/隐私保护
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
|
设计模式 消息中间件 搜索推荐
Java 设计模式——观察者模式:从优衣库不使用新疆棉事件看系统的动态响应
【11月更文挑战第17天】观察者模式是一种行为设计模式,定义了一对多的依赖关系,使多个观察者对象能直接监听并响应某一主题对象的状态变化。本文介绍了观察者模式的基本概念、商业系统中的应用实例,如优衣库事件中各相关方的动态响应,以及模式的优势和实际系统设计中的应用建议,包括事件驱动架构和消息队列的使用。
281 6