肝一肝设计模式【二】-- 工厂模式

news2024/11/28 3:20:05

系列文章目录

肝一肝设计模式【一】-- 单例模式 传送门
肝一肝设计模式【二】-- 工厂模式 传送门


文章目录

  • 系列文章目录
  • 前言
  • 一、简单工厂模式
  • 二、工厂方法模式
  • 三、抽象工厂模式
  • 写在最后


前言

在实际开发过程中,构建对象往往使用new的方式来构建,但随着开发时间的拉长,构建对象的逻辑慢慢会在很多类里使用,那就势必会产生大量的重复代码,那就意味着难以维护,所以我们想把创建对象的代码和业务逻辑分离,并通过一个统一的接口创建对象,然后把创建对象的逻辑封装起来,而这些就是工厂模式所解决的问题


一、简单工厂模式

我们拿动物世界举个栗子(最近陪女鹅看动画片看太多,脑子第一时间想到的只有动物o(* ̄3 ̄)o )
在这里插入图片描述
我们先定义一个Animal接口

public interface Animal {
    
    public void eat();
}

然后再创建两个实现类兔子和老虎

public class Rabbit implements Animal {

    @Override
    public void eat() {
        System.out.println("我是兔子,我吃胡萝卜");
    }
}
public class Tiger implements Animal {

    @Override
    public void eat() {
        System.out.println("我是老虎,我吃肉");
    }
}

再创建一个AnimalFactory工厂类,有两种方式实现:

  1. 使用逻辑判断方式
public class AnimalFactory {

    public Animal create(String name) {
        if("rabbit".equals(name)) {
            return new Rabbit();
        } else if("tiger".equals(name)) {
            return new Tiger();
        } else {
            System.out.println("啥也不是");
            return null;
        }
    }
}

然后我们测试一下:

public class SimpleFactoryTest {
    public static void main(String[] args) {
        AnimalFactory factory = new AnimalFactory();
        factory.create("rabbit").eat();
    }
}

也可将AnimalFactory工厂类的create()方法改为静态方法,这样调用就更方便一点。

  1. 使用反射方式
public class AnimalFactory {

    public Animal create(Class<? extends Animal> c){
	    try {
	        if (null != c) {
	            return c.newInstance();
	        }
	    }catch (Exception e){
	        e.printStackTrace();
	    }
	    return null;
	}
}

我们测试一下:

public class SimpleFactoryTest {
    public static void main(String[] args) {
        AnimalFactory factory = new AnimalFactory();
        Animal animal = factory.create(Tiger.class);
	    animal.eat();
	}
}

简单工厂模式实质:是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例。

二、工厂方法模式

在简单的工厂模式里,我们创建了一个类似工具的类来创建相应的具体类对象,但正因为其太过简单,不符合开闭原则。
工厂方法模式就是把简单工厂中具体的工厂类,划分成两层:抽象工厂层 + 具体的工厂子类层。

在这里插入图片描述
我们上面的工厂类进行拆分

  • AnimalFactory(抽象工厂)
public abstract class AnimalFactory {
    public abstract Animal create();
}
  • RabbitFactory(具体的工厂子类)‘
public class RabbitFactory extends AnimalFactory {
    @Override
    public Animal create() {
        return new Rabbit();
    }
}
  • TigerFactory(具体的工厂子类)
public class TigerFactory extends AnimalFactory {
    @Override
    public Animal create() {
        return new Tiger();
    }
}

测试一下

public class FactoryMethodTest {
    public static void main(String[] args) {
        AnimalFactory factory = new RabbitFactory();
	    Rabbit rabbit = factory.create();
	    rabbit.eat();
	}
}

工厂方法模式实质:不仅仅产品要抽象, 工厂也需要抽象。这样的好处就是更拥抱变化,比如现在需要创建一个Cat对象,就不需要像简单工厂模式去修改create()方法,只需新增一个Cat工厂类即可,遵循了开闭原则。

三、抽象工厂模式

工厂方法模式中,具体工厂A和B,两者除了都是抽象工厂的子类,没有任何其他的交集,是完全独立的两个工厂。

那抽象工厂模式中,具体工厂之间就能产生交际。

抽象工厂模式是这么定义的,提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类。可以理解为将同一类的产品子类归为一类,让他们继承同一个抽象子类,把他们当做一个组。

比如我们新增一个Cat类,我们可以把猫和兔子分类成宠物类型,也可以把猫和老虎分类成猫科动物类型。

所以代码修改一下:

public class AbstractFactoryClient {
    public static void main(String[] args) {
        AnimalFactory factory = new PetFactory();
		factory.createPet().sayA();
		factory.createMaoke().sayB();
		
		factory = new MaokeFactory();
		factory.createPet().sayA();
		factory.createMaoke().sayB();
	}
	// 抽象工厂类
    public interface AnimalFactory {
        Pet createPet();
        Maoke createMaoke();
    }
    
    // 宠物分类抽象
    public interface Pet {
        void sayA();
    }
    
    // 猫科分类抽象
    public interface Maoke {
        void sayB();
    }
    
    // 宠物分类的兔子
    static class RabbitWithPet implements Pet {
    	@Override
        public void sayA() {
            System.out.println("我是宠物兔");
        }
    }

    // 宠物分类的猫
    static class CatWithPet implements Pet {
    	@Override
        public void sayA() {
            System.out.println("我是宠物猫");
        }
    }
    
    // 猫科分类的猫
    static class CatWithMaoke implements Maoke {
    	@Override
        public void sayB() {
            System.out.println("我能上树,所以我是猫科动物的老大");
        }
    }
    
    // 猫科分类的老虎
    static class TigerWithMaoke implements Maoke {
    	@Override
        public void sayB() {
            System.out.println("老大没教我怎么上树");
        }
    }
    
    // 具体工厂类(宠物)
    static class PetFactory implements AnimalFactory{
    	
    	@Override
        public Pet createPet() {
            return new RabbitWithPet();
        }

		@Override
        public Maoke createMaoke() {
            return new CatWithMaoke();
        }
    }

    // 具体工厂类(猫科)
    static class MaokeFactory implements AnimalFactory{
        
        @Override
        public Pet createPet() {
            return new CatWithPet();
        }

        @Override
        public Maoke createMaoke() {
            return new TigerWithMaoke();
        }
    }
}

在抽象工厂模式中,可以不需要知道产品是什么样的,只需要知道是用哪个工厂类就行了。也可以根据子类的共同特性,将它们设计在一起,组成一个相同类型组,就可以很方便的直接调用。但是相对的,产品族比较难以扩展,增加一个产品,就需要增加相应的接口和实现类。


写在最后

工厂模式关心的是最终创建的对象,而不关心创建的过程,这样做的优点是为创建对象提供统一的接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的,在此同时还能给系统带来更大的可扩展性和尽量少的修改量。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nginx搭建以及使用(linux)

1.概念 Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;它可以用来处理静态文件&#xff0c;负载均衡&#xff0c;反向代理等功能。 Nginx的来历是这样的&#xff1a;它是由俄罗斯人伊戈尔赛索耶夫为Rambler.ru站点开发的&#xff0c;第一个公开版本发布于2004年…

java的构造方法

构造方法是 Java中最重要的方法&#xff0c;也是 Java语言中最基本的方法&#xff0c;它直接影响程序的结构。java中不允许重复使用构造方法&#xff0c;但可以重复使用构造函数。 1. Java中只有构造函数可以使用被调用方提供的参数&#xff08;如&#xff1a; int&#xff09;…

作为一名8年测试工程师,因为偷偷接私活被····

接私活 对程序员这个圈子来说是一个既公开又隐私的话题&#xff0c;不说全部&#xff0c;应该大多数程序员都有过想要接私活的想法&#xff0c;当然&#xff0c;也有部分得道成仙的不主张接私活。但是很少有人在公开场合讨论私活的问题&#xff0c;似乎都在避嫌。就跟有人下班后…

Linux进程通信——共享内存

共享内存 共享内存原理与概念函数接口的介绍与使用shmgetshmctlshmatshmdt通信 共享内存的特点共享内存的内核结构 system V消息队列&#xff08;了解&#xff09;system V——初识信号量信号量的预备概念理解信号量信号量的接口与结构 IPC资源的组织方式 共享内存 原理与概念…

在 Edge 中安装 Tampermonkey 的步骤

以下是在 Edge 中安装 Tampermonkey 的步骤&#xff1a; 目录 1. 打开 Edge 浏览器&#xff0c;进入 Tampermonkey 官网&#xff1a;[https://www.tampermonkey.net/](https://www.tampermonkey.net/)。2. 点击页面上方的“下载”按钮&#xff0c;选择“Microsoft Edge”选项。…

2.2.2 redis,memcached,nginx网络组件

课程目标&#xff1a; 1.网络模块要处理哪些事情 2.reactor是怎么处理这些事情的 3.reactor怎么封装 4.网络模块与业务逻辑的关系 5.怎么优化reactor? io函数 函数调用 都有两个作用&#xff1a;io检测 是否就绪 io操作 1. int clientfd accept(listenfd, &addr, &…

BigInteger和BigDecimal

BigInteger 当一个整数很大&#xff0c;大到long都无法保存&#xff0c;就可以使用BigInteger这个类 使用方法&#xff1a;new import java.math.BigInteger;//记得引包 BigInteger bigInteger new BigInteger("33333333333399999999999");//用字符串传入 System…

STM32物联网实战开发(6)——PWM驱动LED灯

PWM驱动LED灯 之前是使用标准库函数配置引脚输出PWM控制呼吸灯&#xff0c;因为开发板上的蜂鸣器是有源的&#xff0c;所以这次还是用来确定LED灯&#xff0c;这次使用的是HAL库&#xff0c;用CubeMX软件初始化PWM功能 PWM输出原理 Period&#xff1a;周期&#xff0c;单位是秒…

10个最流行的向量数据库【AI】

矢量数据库是一种将数据存储为高维向量的数据库&#xff0c;高维向量是特征或属性的数学表示。 每个向量都有一定数量的维度&#xff0c;范围从几十到几千不等&#xff0c;具体取决于数据的复杂性和粒度。 推荐&#xff1a;用 NSDT场景设计器 快速搭建3D场景。 矢量数据库&…

手机短信验证码登录功能的开发实录(机器识别码、短信限流、错误提示、发送验证码倒计时60秒)

短信验证码登录功能 项目分析核心代码1.外部js库调用2.HTML容器构建3.javaScript业务逻辑验证4.后端验证逻辑 总结 短信验证码是通过发送验证码到手机的一种有效的验证码系统&#xff0c;作为比较准确和安全地保证购物的安全性&#xff0c;验证用户的正确性的一种手段&#xff…

Redux的基本使用,从入门到入土

目录 一、初步使用Redux 1.安装Redux 2.配置状态机 二、Redux的核心概念 1.工作流程 2.工作流程 三、优化Redux 1.对action进行优化 2.type常量 3.reducer优化 四、react-redux使用 1.安装react-redux 2.全局注入store仓库 3.组件关联仓库 五、状态机的Hook 1.u…

Day958.代码的分层重构 -遗留系统现代化实战

代码的分层重构 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于代码的分层重构的内容。 来看看如何重构整体的代码&#xff0c;也就是如何对代码分层。 一、遗留系统中常见的模式 一个学校图书馆的借书系统。当时的做法十分“朴素”&#xff0c;在点击“借阅”按钮…

如何使用osquery在Windows上实时监控文件?

导语&#xff1a;Osquery是一个SQL驱动操作系统检测和分析工具&#xff0c;它由Facebook创建&#xff0c;支持像SQL语句一样查询系统的各项指标&#xff0c;可以用于OSX和Linux操作系统。 Osquery是一个SQL驱动操作系统检测和分析工具&#xff0c;它由Facebook创建&#xff0c;…

不得不说的行为型模式-责任链模式

目录 责任链模式&#xff1a; 底层原理&#xff1a; 代码案例&#xff1a; 下面是面试中可能遇到的问题&#xff1a; 责任链模式&#xff1a; 责任链模式是一种行为型设计模式&#xff0c;它允许多个对象在一个请求序列中依次处理该请求&#xff0c;直到其中一个对象能够…

【VM服务管家】VM4.0平台SDK_2.5 全局工具类

目录 2.5.1 全局相机&#xff1a;全局相机设置参数的方法2.5.2 全局相机&#xff1a;获取全局相机列表的方法2.5.3 全局通信&#xff1a;通信管理中设备开启状态管理2.5.4 全局通信&#xff1a;接收和发送数据的方法2.5.5 全局变量获取和设置全局变量的方法 2.5.1 全局相机&…

经典重装上阵,更好用的中小手游戏鼠标,雷柏V300W上手

日常办公、玩游戏都需要用到鼠标&#xff0c;特别是对于游戏玩家来说&#xff0c;一款手感好、易定制的鼠标&#xff0c;绝对是游戏上分的利器。早先雷柏出过一款V300鼠标&#xff0c;距今已有10年历史&#xff0c;当时是很受欢迎&#xff0c;最近南卡又出了一款复刻版的V300W&…

为什么不要相信AI机器人提供的健康信息?

自从OpenAI、微软和谷歌推出了AI聊天机器人&#xff0c;许多人开始尝试一种新的互联网搜索方式&#xff1a;与一个模型进行对话&#xff0c;而它从整个网络上学到的知识。 专家表示&#xff0c;鉴于之前我们倾向于通过搜索引擎查询健康问题&#xff0c;我们也不可避免地会向Ch…

linux下的权限管理

1.shell概念 当我们在进入正文前先给大家普及一些基础概念。 广义上来讲&#xff0c;linux 发行版 linux内核 外壳程序&#xff08;这个外壳程序就相当于 windows gui&#xff08;窗口图形&#xff09;&#xff0c;linux 常用的shell 是 bash&#xff09; 所以&#xff0c…

vue基本语法

目录 一、模板语法 &#xff08;1&#xff09;文本 &#xff08;2&#xff09;原始HTML &#xff08;3&#xff09;属性Attribute &#xff08;4&#xff09;使用JavaScript表达式 二、条件渲染 &#xff08;1&#xff09;v-if&#xff0c;v-else &#xff08;2&#x…

nodejs+vue+elementui学生毕业生离校系统

学生毕业离校系统的开发过程中。该学生毕业离校系统包括管理员、学生和教师。其主要功能包括管理员&#xff1a;首页、个人中心、学生管理、教师管理、离校信息管理、费用结算管理、论文审核管理、管理员管理、留言板管理、系统管理等&#xff0c;前台首页&#xff1b;首页、离…