1.工厂模式的介绍2.工厂模式通过代码的实现
本文首发于CSDN,作者:lomtom 原文链接:https://blog.csdn.net/qq_41929184/article/details/118366444 你的支持就是我最大的动力。
创建者模式模式提供创建对象的机制, 能够提升已有代码的灵活性和可复⽤性。
创建者模式包括:工厂方法、抽象工厂、生成器、原型、单例,这5类。
这一节主要讲述工厂模式:
1.简单工厂模式
•定义:定义一个工厂类,他可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类•核心就是用一个类来负责控制创建实例的过程。• 适用场景:
1.工厂类负责创建对的对象比较少,因为不会造成工厂方法中的业务逻辑过于复杂2.客户端只知道传入工厂类的参数,对如何创建对象不关心
2.工厂模式
•定义:在父类中提供一个创建对象的方法, 允许子类决定实例化对象的类型。•适用场景:
1.当你在编写代码的过程中, 如果无法预知对象确切类别及其依赖关系时, 可使用工厂方法。2.如果你希望用户能扩展你软件库或框架的内部组件, 可使用工厂方法。3.如果你希望复用现有对象来节省系统资源, 而不是每次都重新创建对象, 可使用工厂方法。
场景实例:小葛参加Jd平台的抽奖活动,而此时只有一种奖品奖品是1000元购物卡一张。为了更好的模拟,假设没有不抽中的情况
那么我们来模拟小葛参加抽奖的这个过程,代码如下
目录结构:
类 | 功能 |
---|---|
AwardService | 模拟发放1000元购物卡奖品 |
Test | 测试 |
实现发放奖品类
测试验证
模拟十次抽奖,结果:
场景实例:小葛参加Jd平台的抽奖活动,平台为了增加奖品的多样性,在原来只有一种奖品的情况下新增两种奖品,分别为Iphone12 和3000元现金
如果代码其余部分与现有类已经存在耦合关系, 那么向程序中添加新类其实并没有那么容易。
下面我们不使用设计模式的情况下,我们一般还用if...else...
来实现需求,通过一个标志awardNumber
来表示小葛获得的奖品类型。
工程结构
类 | 功能 |
---|---|
AwardService | 模拟发放三种奖品 |
Test | 测试 |
实现发放奖品类 通过一个变量awardNumber
来表明小葛抽中哪一个奖品,并且发放相应的奖品。
测试验证
这里使用0 - 2的随机数来代表小葛抽中了具体哪种商品,测试结果
小结: 使用if...else...
非常直接的实现了业务需求,如果只从产品需求来说,使用if...else...
确实满足了需求,并且也能缩短上线的时间,但是这样简单粗暴的方式,在一定程度上给我们带来了便捷,但是也种下了一定的隐患。
1.当产品后续迭代时,需要引入更多的需求时,代码将变得臃肿;2.并且也在一定程度上提高的重构代码的难度与成本;3.一旦出现问题,测试所花的时间也会相应的增加。
那么,问题来了,我们怎么使用工厂模式来进行优化呢?
使用简单工厂模式步骤:
1.创建抽象产品接口
2.创建具体产品类 3.创建工厂类 4.客户端调用工厂类
场景实例:小葛参加Jd平台的抽奖活动,平台为了增加奖品的多样性,在原来只有一种奖品的情况下新增两种奖品,分别为Iphone12 和3000元现金
对上面使用if...else...
的代码进行抽取,将其每个奖品发放的功能相应的抽取出来,然后使用一个工厂来决定发放哪一个奖品。
工程结构
我们创建一个发放奖品的接口(AwardService
)和发放奖品接口的实现类,并且使用AwardFactory
来获取AwardService
对象,从而实现奖品的发放。
类 | 功能 |
---|---|
AwardService | 奖品方法接口 |
CashAwardService | 模拟发放现金 |
IphoneAwardService | 模拟发放手机 |
MallCardAwardService | 模拟发放购物卡 |
AwardFactory | 发放奖品工厂 |
Test | 测试 |
实现发放奖品接口与其实现类 首先创建发放奖品的接口。其次创建具体的发放奖品的实现类。
工厂类 使用一个变量awardNumber
来代表小葛是抽中了哪一个奖品,然后来决定具体实现哪一个实现类。
测试验证 用test来模拟客户端发起请求。
结果:
优点:简单工厂模式分离产品的创建者和消费者,有利于软件系统结构的优化,消费者的逻辑较为复杂时,这样的代码风格能够让我们对其功能一目了然; 缺点:但是由于一切逻辑都集中在一个工厂类中,导致了没有很高的内聚性,同时也违背了“开放封闭原则
”。也就是说我需要增加一个其他的奖品,则需要修改工厂类,重新进行编译。
使用简单工厂模式步骤:
1.创建抽象产品接口2.创建具体产品类实现产品接口3.创建工厂(具体创建者)接口4.创建具体产品工厂类实现该工厂接口5.创建工厂类(抽象创建者,可以说是一个调度中心)6.客户端调用工厂类
小疑问?具体创建者与抽象创建者是什么东西? 在本实例中,因为这里有两种类型的工厂,AwardFactory
来实现具体需要创建的产品(来发放需要发放的产品),所以这个工厂叫做具体的创建者,而FactoryFactory
并没有参与到产品的创建,而是将产品的创建延迟到AwardFactory
来进行创建,所以FactoryFactory
被称为抽象的创建者。
场景实例:小葛参加Jd平台的抽奖活动,平台为了增加奖品的多样性,在原来只有一种奖品的情况下新增两种奖品,分别为Iphone12 和3000元现金
工程结构
首先第一步:让所有产品都遵循同一接口。
其次,创建工厂接口(具体创建者),然后创建具体产品的工厂类实现工厂接口(一个工厂只负责生产一个产品,做到专职)
最后,创建抽象创建者工厂,工厂方法中添加临时参数来控制返回的需要发放奖品的类型。
测试验证
结果
从结果中我们可以看出,我们使用工厂模式同样到达了预期效果,相对于最开始使用if...else...
来实现,
1.其更满足设计模式中的单一职责原则
与开闭原则
,我们每一种奖品的发放都由相应的类来进行控制,以及在后续进行扩展的时候,我们能够更加方便的进行扩展。2.其代码可以在一定程度上避免创建者与产品的解耦
当然,面对非常复杂的业务,仅仅使用工厂模式远远是不够的,还需要配合其他的设计模式来进行使用。而对于特别简单的业务,使用工厂模式往往会增加系统的复杂性,具体使用场景还是根据当前的业务来。
1.jdk 的Integer的valueOf方法(静态工厂方法)
JDK在1.5中添加的一项新特性,把-128~127的数字缓存起来了。所以这个范围内的自动装箱的数字都会从缓存中获取,返回同一个数字。这样的好处就是提升性能和节省内存。
2.Mybatis数据源[1](工厂 + 代理)3.Dubbo - Registry提供服务的注册[2] (工厂 + 模板)