【Java设计模式】系列二:工厂方法模式

前言

→继上一篇文章:【Java设计模式】系列一:简单工厂模式

在简单工厂模式中,只提供了一个工厂类,该工厂类对产品类进行实例化,按照设定的处理逻辑,需求化的实例化哪一个产品类。简单工厂模式最大的缺点是当有新产品加入到系统中时,必须修改工厂类,加入必要的处理逻辑,这就违背了七大原则中的“开闭原则”。在简单工厂模式中,所有的产品都是由同一个工厂创建,工厂职责较重,业务逻辑较为复杂,具体产品与工厂类之间的耦合度较高,严重影响了系统的灵活性和可扩展性,而工厂方法基于上述缺点得以优化。

工厂方法模式

工厂方法模式(Factory Method Pattern) 又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式。定义一个创建对象的抽象方法,由子类决定要实例化的类。工厂方法模式将对象的实例化推迟到子类。

工厂模式包含如下具体角色:

  • Product: 抽象产品,定义产品的规范,描述产品的具体特性和功能。
  • ConcreteProduce: 具体产品,实现抽象产品角色所定义的接口,由具体工厂来创建。
  • Factory: 抽象工厂,提供创建产品的接口,调用者通过访问具体工厂方法的来创建产品。
  • ConcreteFactory: 具体工厂,主要实现抽象工厂中的抽象方法,完成具体产品的实例化。

代码示例: 生产汽车案例
创建汽车生产的抽象类(Product:抽象产品角色)

package com.designMode;

/**
 * @Author:bnli
 * @Date:2020/2/8 10:19
 */
public abstract class Care {
    public abstract void produceCar();
}

创建生产路虎揽胜的类(ConcreteProduct:具体产品角色)

package com.designMode;

/**
 * @Author:bnli
 * @Date:2020/2/8 10:25
 */
public class LuhuCar extends Car {
    @Override
    public void produceCar() {
        System.out.println("生产路虎揽胜汽车!");
    }
}

创建生产大众途锐的类(ConcreteProduct:具体产品角色)

package com.designMode;

/**
 * @Author:bnli
 * @Date:2020/2/5 10:27
 */
public class DazCar extends Car {
    @Override
    public void produceCar() {
        System.out.println("生产大众途锐汽车!");
    }
}

创建抽象工厂类(Factory:抽象工厂)

package com.designMode;

/**
 * @Author:bnli
 * @Date:2020/2/8 10:30
 */
public abstract class AcarFactory {
    public abstract Car getCarFactory();
}

创建路虎揽胜工厂类(ConcreteFactory:具体工厂)

package com.designMode;

/**
 * @Author:bnli
 * @Date:2020/2/8 10:35
 */
public class LuhuaFactory extends AcarFactory {
    public Car getCarFactory() {
        return new LuhuCar();
    }
}

创建大众途锐工厂类(ConcreteFactory:具体工厂)

package com.designMode;

/**
 * @Author:bnli
 * @Date:2020/2/8 10:37
 */
public class DazFactory extends AcarFactory {
    public Car getCarFactory() {
        return new DazCar();
    }
}

创建测试类:

package com.designMode;

/**
 * @Author:bnli
 * @Date:2020/2/8 10:50
 */
public class TestCarT {
    public static void main(String[] args) {
        LuhuaFactory luhuaFactory = new LuhuaFactory();
        Car carl = luhuaFactory.getCarFactory();
        carl.produceCar();

        DazFactory dazFactory = new DazFactory();
        Car card = dazFactory.getCarFactory();
        card.produceCar();
    }
}

测试结果:
在这里插入图片描述
转成UML图:
在这里插入图片描述
在这里插入图片描述
工厂方法模式分析总结:

如需拓展其他产品类,只需在最外层添加,不会修改核心代码,符合“符合开闭原则”,解决简单工厂模式的缺点。

工厂方法模式就是对简单工厂模式的改进(或者进一步的抽象),将工厂抽象成两层,AbstractFactory(抽象工厂)和具体实现的工厂子类,程序可以根据创建对象的类型使用对应的工厂子类创建对象。这样讲单个的简单工厂类变成工厂簇,更有利于代码的维护和扩展。

优点与缺点对比:

优点:

  • 基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够使工厂可以自主确定创建何种产品对象,而如何创建这个对象得细节则完全封装在具体工厂内部。工厂方法模式之所以称之为多态工厂模式,是因为所有的具体工厂类都具有同一抽象父类。
  • 使用工厂方法模式的另一个优点是在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了。这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。

缺点:

  • 拓展新产品时,需要重新编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
  • 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度。

应用场景:
比如 java.util.Collection 接口的iterator()、Java 消息服务JMS(Java Messaging Service) 、JDBC 中的工厂方法等。

工厂方法模式的适用环境:

  • 一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
  • 一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
  • 将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定,可将具体工厂类的类名存储在配置文件或数据库中。

工厂方法模式扩展:

  • 使用多个工厂方法 : 在抽象工厂角色中可以定义多个工厂方法,从而使具体工厂角色实现这些不同的工厂方法,这些方法可以包含不同的业务逻辑,以满足对不同的产品对象的需求。
  • 产品对象的重复使用 : 工厂对象将已经创建过的产品保存到一个集合(如数组、List 等)中,然后根据客户对产品的请求,对集合进行查询。如果有满足要求的产品对象,就直接将该产品返回客户端;如果集合中没有这样的产品对象,那么就创建一个新的满足要求的产品对象,然后将这个对象在增加到集合中,再返回给客户端。
  • 多态性的丧失和模式的退化 : 如果工厂仅仅返回一个具体产品对象,便违背了工厂方法的用意,发生退化,此时就不再是工厂方法模式了。一般来说,工厂对象应当有一个抽象的父类型,如果工厂等级结构中只有一个具体工厂类的话,抽象工厂就可以省略,也将发生了退化。当只有一个具体工厂,在具体工厂中可以创建所有的产品对象,并且工厂方法设计为静态方法时,工厂方法模式就退化成简单工厂模式。
发布了34 篇原创文章 · 获赞 44 · 访问量 9087

猜你喜欢

转载自blog.csdn.net/qq_41144667/article/details/104208305
今日推荐