Spring5系列(二) | 工厂设计模式

2021-12-13 09:39:36 浏览数 (1)

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(); 
     }
 }
复制代码

四. 总结

好了,关于工厂设计模式,我们就暂时写这么多,这里边有很多内容都是直接从我的笔记上摘抄的,而笔记中的内容也多半是多年前在知乎上摘录,但是没有记录原文作者和链接,在此表达鸣谢,如有侵权,请联系删除。

0 人点赞