GoF之工厂模式

Spring

  • GoF之工厂模式
    • 工厂模式的三种形态
    • 简单工厂模式
      • 简单工厂模式优缺点
    • 工厂方法模式
      • 工厂方法模式的优缺点


GoF之工厂模式

● 设计模式:一种可以被重复利用的解决方案。

GoF有23种设计模式,还有其它的设计模式,比如:JavaEE的设计模式(DAO模式、MVC模式等)

● 工厂模式是解决对象创建问题的,所以工厂模式属于创建型设计模式。

工厂模式的三种形态

工厂模式通常有三种形态:
● 第一种:简单工厂模式,不属于23种设计模式之一
● 第二种:工厂方法模式
● 第三种:抽象工厂模式

简单工厂模式

Spring中的BeanFactory就使用了简单工厂模式。

简单工厂模式的角色包括三个:
● 抽象产品角色
● 具体产品角色
● 工厂类角色

例:简单工厂模式
抽象产品角色:

package com.w.spring6.factory;

public abstract class Weapon {
    /**
     * 所有的武器都有攻击行为
     */
    public abstract void attack();
}

具体产品角色:
Tank.java

package com.w.spring6.factory;

public class Tank extends Weapon{
    @Override
    public void attack() {
        System.out.println("坦克开炮!");
    }
}

Fighter.java

package com.w.spring6.factory;

public class Fighter extends Weapon{
    @Override
    public void attack() {
        System.out.println("战斗机投下原子弹!");
    }
}

Dagger.java

package com.w.spring6.factory;

public class Dagger extends Weapon{
    @Override
    public void attack() {
        System.out.println("刀他!");
    }
}

工厂类角色:
WeaponFactory.java

package com.w.spring6.factory;

public class WeaponFactory {
    /**
     * 根据不同的武器类型生产武器
     * @param weaponType 武器类型
     * @return 武器对象
     */
    public static Weapon get(String weaponType){
        if (weaponType == null || weaponType.trim().length() == 0) {
            return null;
        }
        Weapon weapon = null;
        if ("TANK".equals(weaponType)) {
            weapon = new Tank();
        } else if ("FIGHTER".equals(weaponType)) {
            weapon = new Fighter();
        } else if ("DAGGER".equals(weaponType)) {
            weapon = new Dagger();
        } else {
            throw new RuntimeException("不支持该武器!");
        }
        return weapon;
    }
}

客户端程序:
Client.java

package com.w.spring6.factory;

public class Client {
    public static void main(String[] args) {
        Weapon weapon1 = WeaponFactory.get("TANK");
        weapon1.attack();

        Weapon weapon2 = WeaponFactory.get("FIGHTER");
        weapon2.attack();

        Weapon weapon3 = WeaponFactory.get("DAGGER");
        weapon3.attack();
    }
}

运行结果:
在这里插入图片描述

简单工厂模式优缺点

优点:

  • 客户端程序不需要关心对象的创建细节,需要哪个对象时,只需要向工厂索要即可,初步实现了责任的分离。客户端只负责“消费”,工厂负责“生产”。生产和消费分离。

缺点:

  • 工厂类集中了所有产品的创造逻辑,形成一个无所不知的全能类,有人把它叫做上帝类。显然工厂类非常关键,不能出问题,一旦出问题,整个系统瘫痪。
  • 不符合OCP开闭原则,在进行系统扩展时,需要修改工厂类。

工厂方法模式

工厂方法模式既保留了简单工厂模式的优点,同时又解决了简单工厂模式的缺点。
工厂方法模式的角色包括:
抽象工厂角色
具体工厂角色
抽象产品角色
具体产品角色

例:工厂方法模式
抽象产品角色:
Weapon.java

package com.w.spring6.factorymethod;

public abstract class Weapon {
    /**
     * 所有的武器都有攻击行为
     */
    public abstract void attack();
}

具体产品角色:
Gun.java

package com.w.spring6.factorymethod;

public class Gun extends Weapon{
    @Override
    public void attack() {
        System.out.println("开枪射击!");
    }
}

Fighter.java

package com.w.spring6.factorymethod;

public class Fighter extends Weapon{
    @Override
    public void attack() {
        System.out.println("战斗机发射核弹!");
    }
}

抽象工厂角色:

package com.w.spring6.factorymethod;

public interface WeaponFactory {
    Weapon get();
}

具体工厂角色:
GunFactory.java

package com.w.spring6.factorymethod;

public class GunFactory implements WeaponFactory{
    @Override
    public Weapon get() {
        return new Gun();
    }
}

FighterFactory.java

package com.w.spring6.factorymethod;

public class FighterFactory implements WeaponFactory{
    @Override
    public Weapon get() {
        return new Fighter();
    }
}

客户端程序:
Client.java

package com.w.spring6.factorymethod;

public class Client {
    public static void main(String[] args) {
        WeaponFactory factory = new GunFactory();
        Weapon weapon = factory.get();
        weapon.attack();

        WeaponFactory factory1 = new FighterFactory();
        Weapon weapon1 = factory1.get();
        weapon1.attack();
    }
}


运行结果:
在这里插入图片描述
如果想扩展一个新的产品,只要新增一个产品类,再新增一个该产品对应的工厂即可,例如新增:匕首
增加:具体产品角色
Dagger.java

package com.w.spring6.factorymethod;

public class Dagger extends Weapon{
    @Override
    public void attack() {
        System.out.println("刀他!");
    }
}

增加:具体工厂角色
DaggerFactory.java

public class DaggerFactory implements WeaponFactory{
    @Override
    public Weapon get() {
        return new Dagger();
    }
}

客户端程序:

        WeaponFactory factory2 = new DaggerFactory();
        Weapon weapon2 = factory2.get();
        weapon2.attack();

运行结果:
在这里插入图片描述
我们可以看到在进行功能扩展的时候,不需要修改之前的源代码,显然工厂方法模式符合OCP原则。

工厂方法模式的优缺点

优点:

  • 一个调用者想创建一个对象,只要知道其名称就可以了。
  • 扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
  • 屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:

  • 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/135017.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用 huggingface_hub 镜像下载 大模型

download.py 👇 import os # 配置 hf镜像 os.environ[HF_ENDPOINT] https://hf-mirror.com# 设置保存的路径 local_dir "XXXXXX"# 设置仓库id model_id "sensenova/piccolo-large-zh"cmd f"huggingface-cli download --resume-downlo…

K8S知识点(六)

(1)资源管理方式1 其他参数 其他参数以json格式显示pod信息 以yaml显示pod信息: 用describe描述容器的详细信息:包括ip啊,镜像啊,端口啊,容器启动经历的历程 创建命名空间Pod: 查询…

[量化投资-学习笔记012]Python+TDengine从零开始搭建量化分析平台-策略回测

上一章节《MACD金死叉策略回测》中,对平安银行这只股票,按照金死叉策略进行了回测。 但通常我们的股票池中有许多股票,每完成一个交易策略都需要对整个股票池进行回测。 下面使用简单的轮询,对整个股票池进行回测。 # 计算单只…

FM模型与POLY2模型

两个核心细节 掌握FM&#xff0c;有两个细节需要注意&#xff1a;参数量级的变化和时间复杂度的变化。 首先对于参数量级&#xff0c;由线性模型到多项式模型到FM模型参数量级变化为&#xff1a; n–>n*n–>kn (k<<n) 其次是由原始FM公式到化简之后的FM公式复杂…

用excel计算一个矩阵的转置矩阵

假设我们的原矩阵是一个3*3的矩阵&#xff1a; 125346789 现在求它的转置矩阵&#xff1a; 鼠标点到一个空白的地方&#xff0c;用来存放结果&#xff1a; 插入-》函数&#xff1a; 选择TRANSPOSE&#xff0c;这个就是求转置矩阵的函数&#xff1a; 点击“继续”&#xff1a…

免费录屏软件哪个好用?免费录屏软件排行榜

对于您的团队&#xff0c;屏幕录像机可以用于多种原因——从为您的网站创建教程到记录反复出现的技术问题&#xff0c;再到向您的营销团队发送快速说明而不是电子邮件。 此外&#xff0c;我们不能忘记产品演示和培训视频&#xff0c;它们可供您团队中的许多部门使用&#xff0…

72 内网安全-域横向CSMSF联动及应急响应初识

目录 演示案例:MSF&CobaltStrike联动ShellWEB攻击应急响应朔源-后门,日志WIN系统攻击应急响应朔源-后门,日志,流量临时给大家看看学的好的怎么干对应CTF比赛 涉及资源 权限维持留到后面在补充&#xff0c;先把后面的知识点给大家讲起来&#xff0c;因为权限维持它是我们前期…

队列Queue

结构特点&#xff1a;先进先出实现模式&#xff1a;单向非循环双指针链表 两个指针分别记录头和尾之所以不用循环链表是添加删除元素都在链表头部进行&#xff0c;不涉及尾部增删操作。 声明队列 声明队列之所以要用到两个结构体是因为除了单个链表节点之外&#xff0c;还需要…

js删除json数据中指定元素

delete 删除数组方法&#xff1a; function removeJSONRows() {var tab {"dataRows": [{"id": 1,"name": "使用部门"},{"id": 2,"name": "车辆走行路线"},{"id": 3,"name": &quo…

合并二叉树(Java)

题目描述 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。合并的规则是&#xff1a;如果两个节点重…

Java的类与Golang的结构体的区别

Java作为一门面向对象&#xff08;OOP&#xff09;的编程语言&#xff0c;它有类&#xff08;class&#xff09;的存在&#xff0c;而对于Golang&#xff0c;它不完全遵从OOP编程语言的设计思想&#xff0c;但它也有类似Java类的结构存在&#xff0c;那就是结构体&#xff08;s…

左值右值笔记

左值右值 左值 左值是表示数据的表达式&#xff08;如变量名或解引用的指针&#xff09; 特点&#xff1a;可以获取地址&#xff0c;可以对他赋值。 位置&#xff1a;左值可以出现在赋值符号左边&#xff0c;也可以出现在赋值符号右边 右值 右值有:字面常量, 表达式返回值 …

2020年-2022年聚合支付牌照机构评级结果分析,D/E有所增加

本文首发于移动支付网&#xff0c;标题“聚合支付机构最新评级结果公布&#xff0c;A-、B级别机构减少”&#xff0c;该文是基于其内容进行了数据修订及部分内容优化而成文。 11月7日&#xff0c;中国支付清算协会发布2022年度收单外包服务机构评级等级结果。本次评级工作&…

在 Azure 上构建和部署自然语言处理模型

自然语言处理&#xff08;Natural Language Processing&#xff0c;NLP&#xff09;是人工智能领域中的重要分支之一&#xff0c;它涉及对人类语言进行理解和分析。在 Azure 平台上&#xff0c;我们可以利用丰富的工具和服务来构建和部署自然语言处理模型&#xff0c;实现从文本…

免费3D骨架工具

免费3D骨架工具 : https://posemy.art/ ControlNet 1.1http://www.coloradmin.cn/o/839105.html?actiononClick https://pan.baidu.com/s/1rh39DI9xVbguLO5l7O4pjA yqqe  网盘里的 预处理器/downloads文件夹&#xff08;包含所有预处理器&#xff09;直接放在 extensions/sd…

【LeetCode刷题-二分查找】--278.第一个错误的版本

278.第一个错误的版本 /* The isBadVersion API is defined in the parent class VersionControl.boolean isBadVersion(int version); */public class Solution extends VersionControl {public int firstBadVersion(int n) {int left 1,right n;while(left < right){int…

企业知识库建设指南:实用经验分享

企业知识库建设是提升内部协作和客户支持效率的重要举措。一个完善的知识库可以帮助企业集中管理和传播知识&#xff0c;提供便捷的自助服务和丰富的编辑工具&#xff0c;从而提升用户体验和品牌好感度。接下来就分享一些经验&#xff0c;关于该如何构建一个高效的企业知识库。…

TCP协议(建议收藏)

1. TCP特点 有连接&#xff1a;需要双方建立连接才能通信&#xff0c;在socket编程中服务端new ServerSocket(port)需要绑定端口&#xff0c;在客服端new Socket(serverIp, serverPort)与服务端建立连接可靠传输&#xff1a;确认应答机制&#xff0c;超时重传机制面向字节流&a…

【文末送JAVA书】包头开发发展

【点我-这里送书】 本人详解 作者&#xff1a;王文峰&#xff0c;参加过 CSDN 2020年度博客之星&#xff0c;《Java王大师王天师》 公众号&#xff1a;JAVA开发王大师&#xff0c;专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生&#xff0c;期待你的…