spring中大量使用的工厂设计模式,所以我们这个章节先简单的了解下工厂设计模式的内容。
工厂设计模式属于创建型模式中的一种。在GOF中的定义:
“Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.”(在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。)
广义上的工厂模式其实分为三种,分别是简单工厂模式(simple factory),工厂方法模式(factory method)和抽象工厂(abstract factory)模式。
为什么要使用工厂模式:
工厂模式的主要好处就是解耦合,这个词好像比较耳熟吧,我们在spring概述的章节中就提高了spring的主要功效也是解耦合,简直不谋而合。同时工厂模式的主要作用是对象的创建和使用过程分开。而对于spring而言就是他负责了对象的创建过程,所以我们只需要关注对象的使用过程就可以了,这样也就大大地简化了我们的开发过程。同时降低了代码的重复和维护成本。因为有了工厂,我们就不需要书写对象的创建过程了。
一. 简单工厂模式
interfaceMouse{ voidsayHi(); } classDellMouseimplementsMouse{ publicvoidsayHi(){ System.out.println("hi,DellMouse") } } classHpMouseimplementsMouse{ publicvoidsayHi(){ System.out.println("hi,HpMouse") } } classMouseFacotry{ publicstaticMousecreateMouse(inti){ switch(i){ case0:returnnewDellMouse();break; case1:returnnewHpMouse();break; default:returnnull; } } } 复制代码
简单工厂在实际应用中相对于其他工厂模式用的相对少,并且它违背了我们在概述中说的开放-封闭原则。因为每次你要添加一个功能,都需要在switch-case或者 if-else中去修改代码,添加分支条件 使用场景: 需要创建的对象较少,客户端不关心对象的创建过程 角色:工厂角色, 抽象产品角色(Mouse) ,具体产品角色(DellMouse, HpMouse)
二. 工厂方法模式
工厂方法模式应该是工厂模式家族中使用最多的模式,一般项目中存在最多的就是这个模式。 工厂方法模式是简单工厂模式的进一步深化,在工厂方法模式中,我们不在提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。
适用场景:
- 一个类不知道它所需要的对象的类: 在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道它所对应的工厂即可,具体的产品对象由具体工厂类创建。客户端需要知道创建具体产品的工厂类
- 一个类通过其子类来指定创建哪个对象: 在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏
- 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中
角色分配
- 抽象工厂(Abstract factory): 是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口
- 具体工厂(Concrete factory): 这是实现抽象工厂接口的具体工厂类,包含于应用长须密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象
- 抽象产品(Abstract product) : 工厂方法模式所创建的对象的超类型,也就是产品对象的公共父类或共同接口
- 具体产品(Concrete product): 这个角色实现了抽象产品角色所定义的接口。某具体产品的由专门的具体工厂创建,他们之间往往一一对应。
代码示例
publicinterfaceMouseFactory{ MousegetMouse(); } publicclassDellMouseFactoryimplementsMouseFactory{ publicMousegetMouse(){ returnnewDellMouse(); } } publicclassHpMouseFactoryimplementsMouseFactory{ publicMousegetMouse(){ returnnewHpMouse(); } } publicinterfaceMouse{ voidsayHi(); } publicclassDellMouseimplementsMouse{ publicvoidsayHi(){ System.out.println("hi,DellMouse") } } publicclassHpMouseimplementsMouse{ publicvoidsayHi(){ System.out.println("hi,HpMouse") } } publicclassTest{ publicstaticvoidmain(String[] args){ MouseFactorydellFac=newDellMouseFactory(); MousedellMouse=dellFac.getMouse(); dellMouse.sayHi(); } } 复制代码
三. 抽象工厂模式
在工厂方法模式中,其实我们有一个潜在的意识。那就是我们生产的都是同一类产品。抽象工厂模式是工厂方法的进一步深化,在这个模式中工厂类不单单可以创建一种产品,而是可以创建一组产品。抽象工厂应该是比较难理解的一个工厂模式了
适用场景
和工厂方法一样客户端不需要知道它所创建的对象类 需要一组对象共同完成某种功能,并且可能存在多组对象完成不同功能的情况(同属同一个产品族的产品) 系统结构稳定,不会频繁增加对象(因为一增加就需要修改原有代码,不符合开闭原则)
角色分配
- 抽象工厂: 是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
- 具体工厂: 是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象。
- 抽象产品:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
- 具体产品:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。在抽象工厂中创建的产品属于同一产品族,这不同于工厂模式中的工厂只创建单一产品,我后面也会详解介绍到。
- 抽象工厂和工厂方法中的工厂区别: 抽象工厂是生产一整套产品的(至少要生产两个产品),这些产品必须相互是有关系或有依赖的,而工厂方法的工厂是生产单一的产品的工厂。
实例
我们以吃鸡游戏举例。游戏中有各种枪。假设现在存在AK,M4A1两类枪,每一种枪对应一种子弹。我们现在这样考虑生产AK的工厂可以顺带生产AK子弹,生产M4A1的工厂可以生产其锁对象的子弹。 创建相关接口:
枪:
publicinterfaceGun{ publicvoidshooting(); }
子弹:
publicinterfaceBullet{ publicvoidload(); }
创建对应实现类 AK:
publicclassAKimplementsGun{ publicvoidshooting(){ System.out.println("shooting with AK"); } }
M4A1:
public class M4A1 implements Gun{ public void shooting(){ System.out.println("shooting with M4A1"); } }
AK子弹:
publicclassAK_BulletimplementsBullet { publicvoidload() { System.out.println("Load bullets with AK"); } }
M4A1子弹类
publicclassM4A1_BulletimplementsBullet { publicvoidload() { System.out.println("Load bullets with M4A1"); } }
创建工厂
publicinterfaceFactory{ publicGunproduceGun(); publicBulletproduceBullet(); } publicclassAKFacimplementsFactory{ publicGunproduceGun(){ returnnewAK(); } publicBulletproduceBullet(){ returnnewAK_Bullet(); } } publicclassM4A1FacimplementsFactory{ publicGunproduceGun(){ returnnewM4A1(); } publicBulletproduceBullet(){ returnnewM4A1_Bullet(); } }
测试
publicclassTest{ publicstaticvoidmain(String[] args){ Factoryfactory; Gungun; Bulletbullet; factory=newAKFac(); bullet=factory.produceBullet(); bullet.load(); gun=factory.produceGun(); gun.shooting(); } }
四. 总结
好了,关于工厂设计模式,我们就暂时写这么多,这里边有很多内容都是直接从我的笔记上摘抄的,而笔记中的内容也多半是多年前在知乎上摘录,但是没有记录原文作者和链接,在此表达鸣谢,如有侵权,请联系删除。