工厂模式包括简单工厂,工厂方法,抽象工厂,这里分别介绍前后端工厂模式以及示例
(前端)工厂模式
简单工厂
简单工厂模式又叫静态工厂模式,由一个工厂对象决定创建某一种产品对象类的实例,主要用来创建同一类对象
简单工厂在调用return new的时候使用
比如说,在实际的项目中,我们常常需要根据用户的权限来渲染不同的页面,高级权限的用户所拥有的页面有些是无法被低级权限的用户所查看,所以我们可以在不同权限等级用户的构造函数中,保存该用户能够看到的页面。
1 | let UserFactory = function (role) { |
总结:在上面的例子中,UserFactory就是一个简单工厂,在该函数中有3个构造函数分别对应不同的权限的用户,当我们调用工厂函数时,只需要传递superAdmin, admin, user这三个可选参数中的一个获取对应的实例对象
优点:
简单工厂的优点在于,你只需要一个正确的参数,就可以获取到你所需要的对象,而无需知道其创建的具体细节;
缺点:
在函数内包含了所有对象的创建逻辑(构造函数)和判断逻辑的代码,每增加新的构造函数还需要修改判断逻辑代码,我们的对象不是上面的3个而是30个或更多时,这个函数会成为一个庞大的超级函数,便得难以维护,简单工厂只能作用于创建的对象数量较少,对象的创建逻辑不复杂时使用;
工厂方法
1 | //安全模式创建的工厂方法函数 |
总结:在简单工厂中,如果我们新增加一个用户类型,需要修改两个地方的代码,一个是增加新的用户构造函数,一个是在逻辑判断中增加对新的用户的判断,而在抽象工厂方法中,我们只需要在UserFactory.prototype中添加就可以啦。
(后端)工厂模式
(1)简单工厂(Simple Factory)模式,又称静态工厂方法模式(Static Factory Method Pattern)。
(2)工厂方法(Factory Method)模式,又称多态性工厂(Polymorphic Factory)模式或虚拟构造子(Virtual Constructor)模式;
(3)抽象工厂(Abstract Factory)模式,又称工具箱(Kit 或Toolkit)模式。
为什么要用工厂模式
(1) 解耦 :把对象的创建和使用的过程分开
(2)降低代码重复: 如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。
(3) 降低维护成本 :由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建某个对象的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。
适用场景
(1)需要创建的对象较少。
(2)客户端不关心对象的创建过程。
简单工厂
@Override是什么注解
@Override 的作bai用是:如果想重写父类的方du法,比如toString()方法的话zhi,在方法前面加上@Override 系统dao可以帮你检查方法的正确性。
(1)创建Shape接口
1 | public interface Shape { |
(2)创建实现该接口的具体图形类
圆形
1 | public class Circle implements Shape { |
长方形
1 | public class Rectangle implements Shape { |
正方形
1 | public class Square implements Shape { |
(3)创建工厂类:
1 | public class ShapeFactory { |
(4)测试方法:
1 | public class Test { |
输出结果:
1 | Circle |
这样的实现有个问题,如果我们新增产品类的话,就需要修改工厂类中的getShape()
方法,这很明显不符合 开放-封闭原则 。
工厂方法
上面简单工厂例子中的图形接口以及相关图像实现类不变。我们只需要增加一个工厂接口以及实现这个接口的工厂类即可。
(1)增加一个工厂接口:
1 | public interface Factory { |
(2)增加相关工厂类:
圆形工厂类
1 | public class CircleFactory implements Factory { |
长方形工厂类
1 | public class RectangleFactory implements Factory{ |
圆形工厂类
1 | public class SquareFactory implements Factory{ |
(3)测试:
1 | public class Test { |
输出结果:
1 | Circle |
适用场景
一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏
将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。
抽象工厂
适用场景
和工厂方法一样客户端不需要知道它所创建的对象的类。
需要一组对象共同完成某种功能时,并且可能存在多组对象完成不同功能的情况。(同属于同一个产品族的产品)
系统结构稳定,不会频繁的增加对象。(因为一旦增加就需要修改原有代码,不符合开闭原则)
场景:
不知道大家玩过穿越火线或者吃鸡这类游戏了吗,游戏中存在各种枪。我们假设现在存在AK、M4A1两类枪,每一种枪对应一种子弹。我们现在这样考虑生产AK的工厂可以顺便生产AK使用的子弹,生产M4A1的工厂可以顺便生产M4A1使用的子弹。(AK工厂生产AK系列产品包括子弹啊,AK枪的类型啊这些,M4A1工厂同理)
抽象工厂模式实例
(1)创建相关接口:
枪
1 | public interface Gun { |
子弹
1 | public interface Bullet { |
(2)创建接口对应实现类:
AK类
1 | public class AK implements Gun{ |
M4A1类
1 | public class M4A1 implements Gun { |
AK子弹类
1 | public class AK_Bullet implements Bullet { |
M4A1子弹类
1 | public class M4A1 |
(3)创建工厂接口
1 | public interface Factory { |
(4)创建具体工厂
生产AK和AK子弹的工厂
1 | public class AK_Factory implements Factory{ |
生产M4A1和M4A1子弹的工厂
1 | public class M4A1_Factory implements Factory{ |
(5)测试
1 | public class Test { |
输出结果:
1 | Load bullets with AK |
参考文章: https://developer.51cto.com/art/201904/594382.htm
https://www.imooc.com/article/31360