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

news/2024/11/23 20:51:51/

系列文章目录

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


文章目录

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


前言

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


一、简单工厂模式

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

public interface Animal {public void eat();
}

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

public class Rabbit implements Animal {@Overridepublic void eat() {System.out.println("我是兔子,我吃胡萝卜");}
}
public class Tiger implements Animal {@Overridepublic 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 {@Overridepublic Animal create() {return new Rabbit();}
}
  • TigerFactory(具体的工厂子类)
public class TigerFactory extends AnimalFactory {@Overridepublic 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 {@Overridepublic void sayA() {System.out.println("我是宠物兔");}}// 宠物分类的猫static class CatWithPet implements Pet {@Overridepublic void sayA() {System.out.println("我是宠物猫");}}// 猫科分类的猫static class CatWithMaoke implements Maoke {@Overridepublic void sayB() {System.out.println("我能上树,所以我是猫科动物的老大");}}// 猫科分类的老虎static class TigerWithMaoke implements Maoke {@Overridepublic void sayB() {System.out.println("老大没教我怎么上树");}}// 具体工厂类(宠物)static class PetFactory implements AnimalFactory{@Overridepublic Pet createPet() {return new RabbitWithPet();}@Overridepublic Maoke createMaoke() {return new CatWithMaoke();}}// 具体工厂类(猫科)static class MaokeFactory implements AnimalFactory{@Overridepublic Pet createPet() {return new CatWithPet();}@Overridepublic Maoke createMaoke() {return new TigerWithMaoke();}}
}

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


写在最后

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


http://www.ppmy.cn/news/53773.html

相关文章

​UWA报告使用技巧小视频,你get了么?(第十弹)

本期UWA报告使用小技巧将分享“回归测试”、“CPU压力较大”、“内存压力较大”这三种不同场景下&#xff0c;使用GOT Online测试时UWA推荐的参数开关配置。项目组可以根据问题排查的需求&#xff0c;自定义相应模块的开关&#xff0c;以便实现在尽可能不干扰你想获得的数据类型…

【VM服务管家】VM4.0平台SDK_2.4 结果获取类

目录 2.4.1 数据结果&#xff1a;通过流程输出或模块输出获取数据结果的方法2.4.2 流程运行&#xff1a;所有流程运行结束的回调方法2.4.3 模块回调&#xff1a;所有模块运行结束的回调方法2.4.4 加密狗回调&#xff1a;获取加密狗状态的回调方法2.4.5 方案加载&#xff1a;方案…

【Hadoop-HDFS】HDFS中Fsimage与Edits详解

【Hadoop-HDFS】HDFS中Fsimage与Edits详解 1&#xff09;概述2&#xff09;NameNode元数据解析3&#xff09;Fsimage3.1.Fsimage 的作用3.2.FSimage 的文件信息查看 4&#xff09;Edits4.1.Edits 的作用4.2.Edits 的文件信息查看 5&#xff09;元数据信息目录的配置 1&#xff…

报告打印的相关CAPL函数,实例代码演示汇总

🍅 我是蚂蚁小兵,专注于车载诊断领域,尤其擅长于对CANoe工具的使用🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】🍅 玩转CANoe,博客目录大全,点击跳转👉 目录 📙1 测试用例中报告打印相关1.1 TestCaseTitle1.2 TestCaseDescripti…

PAt A1015 Reversible Primes

1015 Reversible Primes 分数 20 作者 CHEN, Yue 单位 浙江大学 A reversible prime in any number system is a prime whose "reverse" in that number system is also a prime. For example in the decimal system 73 is a reversible prime because its rever…

C# WebService的开发以及客户端调用

目录 1、WebService简介 1.1 什么是XML&#xff1f; 1.2 什么是Soap&#xff1f; 1.3 什么是WSDL&#xff1f; 2、WebService与WebApi的区别与优缺点 2.1 WebService与WebApi的区别&#xff1a; 2.2 WebService的优缺点&#xff1a; 2.3 WebApi的优缺点&#xff1a; 3…

【C++】C++内存管理,模板

目录 C内存管理operator new 和 operator delete关于 new C[N] 和 delete[ ]定位new 模板函数模板类模板 C内存管理 C中通过 new 和 delete 两个操作符实现动态内存管理 为自定义类型设计&#xff0c;可以在申请空间得同时初始化使用 new 先申请空间&#xff0c;再调用构造使…

03 KVM虚拟机镜像制作

文章目录 03 KVM虚拟机镜像制作3.1 概述3.2 制作镜像3.2.1 使用root用户安装qemu-img软件包3.2.2 使用qemu-img工具的创建镜像文件 3.3 修改镜像磁盘空间大小3.3.1 查询当前虚拟机镜像磁盘空间大小3.3.2 修改镜像磁盘空间大小3.3.3 查询修改后的镜像磁盘空间大小 03 KVM虚拟机镜…