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而言就是他负责了对象的创建过程,所以我们只需要关注对象的使用过程就可以了,这样也就大大地简化了我们的开发过程。同时降低了代码的重复和维护成本。因为有了工厂,我们就不需要书写对象的创建过程了。
一. 简单工厂模式
代码语言:javascript复制interface Mouse{
void sayHi();
}
class DellMouse implements Mouse{
public void sayHi(){
System.out.println("hi,DellMouse")
}
}
class HpMouse implements Mouse{
public void sayHi(){
System.out.println("hi,HpMouse")
}
}
class MouseFacotry{
public static Mouse createMouse(int i){
switch(i){
case 0:return new DellMouse();break;
case 1:return new HpMouse();break;
default:return null;
}
}
}
复制代码
简单工厂在实际应用中相对于其他工厂模式用的相对少,并且它违背了我们在概述中说的开放-封闭原则。因为每次你要添加一个功能,都需要在switch-case或者 if-else中去修改代码,添加分支条件 使用场景: 需要创建的对象较少,客户端不关心对象的创建过程 角色:工厂角色, 抽象产品角色(Mouse) ,具体产品角色(DellMouse, HpMouse)
二. 工厂方法模式
工厂方法模式应该是工厂模式家族中使用最多的模式,一般项目中存在最多的就是这个模式。 工厂方法模式是简单工厂模式的进一步深化,在工厂方法模式中,我们不在提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说每个对象都有一个与之对应的工厂。
适用场景:
- 一个类不知道它所需要的对象的类: 在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道它所对应的工厂即可,具体的产品对象由具体工厂类创建。客户端需要知道创建具体产品的工厂类
- 一个类通过其子类来指定创建哪个对象: 在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏
- 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无需关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中
角色分配
- 抽象工厂(Abstract factory): 是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口
- 具体工厂(Concrete factory): 这是实现抽象工厂接口的具体工厂类,包含于应用长须密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象
- 抽象产品(Abstract product) : 工厂方法模式所创建的对象的超类型,也就是产品对象的公共父类或共同接口
- 具体产品(Concrete product): 这个角色实现了抽象产品角色所定义的接口。某具体产品的由专门的具体工厂创建,他们之间往往一一对应。
代码示例
代码语言:javascript复制public interface MouseFactory{
Mouse getMouse();
}
public class DellMouseFactory implements MouseFactory{
public Mouse getMouse(){
return new DellMouse();
}
}
public class HpMouseFactory implements MouseFactory{
public Mouse getMouse(){
return new HpMouse();
}
}
public interface Mouse{
void sayHi();
}
public class DellMouse implements Mouse{
public void sayHi(){
System.out.println("hi,DellMouse")
}
}
public class HpMouse implements Mouse{
public void sayHi(){
System.out.println("hi,HpMouse")
}
}
public class Test{
public static void main(String[] args){
MouseFactory dellFac = new DellMouseFactory();
Mouse dellMouse = dellFac.getMouse();
dellMouse.sayHi();
}
}
复制代码
三. 抽象工厂模式
在工厂方法模式中,其实我们有一个潜在的意识。那就是我们生产的都是同一类产品。抽象工厂模式是工厂方法的进一步深化,在这个模式中工厂类不单单可以创建一种产品,而是可以创建一组产品。抽象工厂应该是比较难理解的一个工厂模式了
适用场景
和工厂方法一样客户端不需要知道它所创建的对象类 需要一组对象共同完成某种功能,并且可能存在多组对象完成不同功能的情况(同属同一个产品族的产品) 系统结构稳定,不会频繁增加对象(因为一增加就需要修改原有代码,不符合开闭原则)
角色分配
- 抽象工厂: 是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
- 具体工厂: 是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象。
- 抽象产品:工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
- 具体产品:抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。在抽象工厂中创建的产品属于同一产品族,这不同于工厂模式中的工厂只创建单一产品,我后面也会详解介绍到。
- 抽象工厂和工厂方法中的工厂区别: 抽象工厂是生产一整套产品的(至少要生产两个产品),这些产品必须相互是有关系或有依赖的,而工厂方法的工厂是生产单一的产品的工厂。
实例
我们以吃鸡游戏举例。游戏中有各种枪。假设现在存在AK,M4A1两类枪,每一种枪对应一种子弹。我们现在这样考虑生产AK的工厂可以顺带生产AK子弹,生产M4A1的工厂可以生产其锁对象的子弹。 创建相关接口:
枪:
代码语言:javascript复制public interface Gun{
public void shooting();
}
复制代码
子弹:
代码语言:javascript复制public interface Bullet{
public void load();
}
复制代码
创建对应实现类 AK:
代码语言:javascript复制 public class AK implements Gun{
public void shooting(){
System.out.println("shooting with AK");
}
}
复制代码
M4A1:
代码语言:javascript复制public class M4A1 implements Gun{
public void shooting(){
System.out.println("shooting with M4A1");
}
}
复制代码
AK子弹:
代码语言:javascript复制 public class AK_Bullet implements Bullet {
@Override
public void load() {
System.out.println("Load bullets with AK");
}
}
复制代码
M4A1子弹类
代码语言:javascript复制 public class M4A1_Bullet implements Bullet {
@Override
public void load() {
System.out.println("Load bullets with M4A1");
}
}
复制代码
创建工厂
代码语言:javascript复制public interface Factory{
public Gun produceGun();
public Bullet produceBullet();
}
public class AKFac implements Factory{
public Gun produceGun(){
return new AK();
}
public Bullet produceBullet(){
return new AK_Bullet();
}
}
public class M4A1Fac implements Factory{
public Gun produceGun(){
return new M4A1();
}
public Bullet produceBullet(){
return new M4A1_Bullet();
}
}
复制代码
测试
代码语言:javascript复制public class Test{
public static void main(String[] args){
Factory factory;
Gun gun;
Bullet bullet;
factory =new AKFac();
bullet=factory.produceBullet();
bullet.load();
gun=factory.produceGun();
gun.shooting();
}
}
复制代码
四. 总结
好了,关于工厂设计模式,我们就暂时写这么多,这里边有很多内容都是直接从我的笔记上摘抄的,而笔记中的内容也多半是多年前在知乎上摘录,但是没有记录原文作者和链接,在此表达鸣谢,如有侵权,请联系删除。