工厂方法模式、抽象工厂模式

工厂系列

定义:

  • 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。
  • 工厂方法模式、抽象工厂模式_第1张图片

分类:

工厂模式在《Java 与模式》中分为三类:这三种模式从上到下逐步抽象,并且更具一般性

  1. 简单工厂模式(Simple Factory)
  2. 工厂方法模式(Factory Method)
  3. 抽象工厂模式(Abstract Factory)

GOF 在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

工厂方法模式、抽象工厂模式_第2张图片

简单工厂模式

  • 简单工厂模式又称静态工厂方法模式。重命名上就可以看出这个模式一定很简单。它存 在的目的很简单:定义一个用于创建对象的接口。

组成:

工厂方法模式、抽象工厂模式_第3张图片
工厂方法模式、抽象工厂模式_第4张图片

案例:

抽象产品角色 Car

public interface Car {
    void drive();
}

具体产品角色

  • 奔驰
public class Benz implements Car{
    @Override
    public void drive() {
        System.out.println("Driving Benz ");
    }
}
  • 宝马
public class Bmw  implements Car{
    @Override
    public void drive() {
        System.out.println("Driving Bmw ");
    }
}

工厂类角色 SimpleFactory

public class SimpleFactory {

    //工厂方法.注意返回类型为抽象产品角色
    public static Car driverCar(String s) throws Exception {

        if (s.equalsIgnoreCase("Benz")) {
            return new Benz();
        } else if (s.equalsIgnoreCase("Bmw")) {
            return new Bmw();
        }else {
            throw  new Exception();
        }
    }
}

测试类 Main

public class Main {
    public static void main(String[] args) throws Exception {

        Car car = SimpleFactory.driverCar("benz");

        car.drive();
    }
}

工厂方法模式、抽象工厂模式_第5张图片
工厂方法模式、抽象工厂模式_第6张图片

简单工厂模式适用场景

  • 简单工厂适用于工厂类负责创建的对象较少的场景,且客户端只需要传入工厂类的参数,对于如何创建对象的逻辑不需要关心

简单工厂模式缺点

  • 假如每种产品创建不仅仅只是实例化一个对象,还有其他逻辑需要处理,那么我们无法直接使用一句反射,避免不了写很多if(亦或者用switch循环),这样的话每新增一个产品我们都需要修改工厂实现类,随着产品链越来越丰富,工厂的职责会变得越来越多,久而久之会越来越难以维护。

工厂方法模式

  • 工厂方法模式是指定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个对象,工厂方法让类的实例化推迟到子类中进行,
  • 在工厂方法模式中用户只需要关心所需产品对应的工厂,无须关心创建细节,而且加入新的产品符合开闭原则。

组成:

工厂方法模式、抽象工厂模式_第7张图片
工厂方法模式、抽象工厂模式_第8张图片
工厂方法模式、抽象工厂模式_第9张图片

案例:

抽象工厂角色 CarFactory

public interface CarFactory {
    Car driverCar();
}

具体工厂角色 BenzFactory,BmwFactory

public class BenzFactory implements CarFactory{
    @Override
    public Car driverCar() {
        return new Benz();
    }
}
public class BmwFactory implements CarFactory{
    @Override
    public Car driverCar() {
        return new Bmw();
    }
}

抽象产品角色 Car

public interface Car {
    void drive();
}

具体产品角色

  • 奔驰
public class Benz implements Car{
    @Override
    public void drive() {
        System.out.println("Driving Benz ");
    }
}
  • 宝马
public class Bmw  implements Car{
    @Override
    public void drive() {
        System.out.println("Driving Bmw ");
    }
}

测试类 Main

public class Main {
    public static void main(String[] args) throws Exception {

        // Car car = SimpleFactory.driverCar("benz");

        CarFactory factory = new BmwFactory();
        Car car = factory.driverCar();
        car.drive();
    }
}

工厂方法模式、抽象工厂模式_第10张图片
看完这个例子家应该很明白工厂方法和简单工厂的区别了,简单工厂就是所有产品都由一个工厂类一个方法来创建,而工厂方法将工厂的职责也进行细化了,每种产品都由自己特定的工厂来生产,这也是单一职责原则的体现。

工厂方法模式适用场景

  1. 当客户程序不需要知道要使用对象的创建过程。
  2. 客户程序使用的对象存在变动的可能,或者根本就不知道使用哪一个具体的对象。

工厂模式优点

  1. 工厂方法克服了简单工厂违背开放-封闭原则的缺点,又保持了封装对象创建过程的优点。
  2. 封装了对象的创建,使得要更换对象时,不需要做大的改动就可实现,降低了客户程序与产品对象的耦合
  3. 工厂方法模式是简单工厂模式的进一步抽象和推广。由于使用了多态性,工厂方法模式保持了简单工厂模式的优点,而且克服了它的缺点。

工厂方法模式缺点

  1. 类的个数容易过多,增加复杂度。
  2. 增加了系统的抽象性和理解难度

抽象工厂

产品族

产品族: 位于不同产品等级结构中,功能相关联的产品组成的家族。

假设BmwFactory,BenzFactory不但造汽车,还制造飞机 坦克.

  • 那么Bmw厂家的car ,plane ,tank就是一族.
  • 同样Benz厂家的car ,plane ,tank也是一族.

而BmwFactory 和BenzFactory 就是两个产品树(产品层次结构);

工厂方法模式、抽象工厂模式_第11张图片

工厂方法模式、抽象工厂模式_第12张图片

使用抽象工厂模式还要满足一下条件:

  1. 系统中有多个产品族,而系统一次只可能消费其中一族产品。
  2. 同属于同一个产品族的产品以其使用

组成;

抽象工厂模式的各个角色(和工厂方法的如出一辙):
工厂方法模式、抽象工厂模式_第13张图片
工厂方法模式、抽象工厂模式_第14张图片

案例:

抽象工厂角色 AbstractFactory

public interface AbstractFactory {
    //制造汽车
    abstract Car driverCar();

    //制造飞机
    abstract plane driverPlane();

    //制造坦克
    abstract tank driverTank();

}

具体工厂角色 BenzFactory,BmwFactory

  • 奔驰工厂
public class BenzFactory implements AbstractFactory {
    @Override
    public Car driverCar() {
        return new BenzCar();
    }

    @Override
    public plane driverPlane() {
        return new BenzPlane();
    }

    @Override
    public tank driverTank() {
        return new BenzTank();
    }
}

  • 宝马工厂
public class BmwFactory implements AbstractFactory {
    @Override
    public Car driverCar() {
        return new BmwCar();
    }

    @Override
    public plane driverPlane() {
        return new BmwPlane();
    }

    @Override
    public tank driverTank() {
        return new BmwTank();
    }
}

测试类 main

public class Main {
    public static void main(String[] args) throws Exception {

        AbstractFactory factory = new BmwFactory();

        Car car = factory.driverCar();
        plane plane = factory.driverPlane();
        tank tank = factory.driverTank();

        car.drive();
        plane.drive();
        tank.drive();
    }
}

工厂方法模式、抽象工厂模式_第15张图片
工厂方法模式、抽象工厂模式_第16张图片
工厂方法模式、抽象工厂模式_第17张图片

抽象工厂模式为创建一组对象提供了一种解决方案。 与工厂方法模式相比, 抽象工厂模式中的具体工厂不只是创建一种具体对象,它负责创建一组(族)具体对象。

抽象工厂使用场景:

当我们有一系列产品(如上面的car,tank,plane)。而这一系列产品每种产品又需要具有不同的创建方法

抽象工厂优点:

  1. 抽象工厂模式隔离了具体类的生成, 使得客户并不需要知道什么被创建。 由于这种隔离,更换一个具体工厂就变得相对容易,
    所有的具体工厂都实现了抽象工厂中定义的那些公共接口, 因此只需改变具体工厂的实例, 就可以在某种程度上改变整个软件系统的行为。
  2. 当一个族中的多个对象被设计成一起工作时, 它能够保证客户端始终只使用同一个族中的对象。
  3. 增加新的族很方便, 无须修改已有系统, 符合“开闭原则”。

抽象工厂缺点:

  1. 规定了所有可能被创建的产品集合,产品族中扩展新的产品困难,需要修改抽象工厂 的接口。
  2. 增加了系统的抽象性和理解难度。

抽象工厂模式在spring源码中的应用

在 Spring 中,BeanFactory 是用于管理 Bean 的一个工厂,所有工厂都是 BeanFactory 的子类。这样我们可以通过 IOC 容器来管理访问 Bean,根据不同的策略调用 getBean() 方法,从而获得具体对象。

工厂方法模式、抽象工厂模式_第18张图片

BeanFactory 的子类主要有 ClassPathXmlApplicationContext、XmlWebApplicationContext、StaticWebApplicationContext、StaticApplicationContext。
在 Spring 中,DefaultListableBeanFactory 实现了所有工厂的公共逻辑

工厂方法模式、抽象工厂模式_第19张图片
详情看Spring源码–01–Spring IOC简述

工厂方法模式、抽象工厂模式_第20张图片

你可能感兴趣的:(23种设计模式,工厂方法模式,抽象工厂模式,java)