interface

Factory Method

1. 概述

定义一个用于创建对象的接口, 让实现类决定实例化哪一个类. 工厂方法使一个类的实例化延迟到其接口实现类.

2. 适用性

  1. 当一个类不知道它所必须创建的对象的类的时候;
    2. 当一个类希望由它的子类来指定它所创建的对象的时候;
    3. 当类将创建对象的职责委托给多个帮助子类中的某一个, 并且你希望将哪一个帮助子类是代理者这一信息局部化的时候.

3. 代码实现

image.png

比如我们现在想要创建 Worker 接口的实例 TeacherFarmer:

  1. interface Worker {
  2. void work();
  3. }
  4. class Teacher implements Worker {
  5. @Override
  6. public void work() {
  7. System.out.println("老师在工作");
  8. }
  9. }
  10. class Farmer implements Worker {
  11. @Override
  12. public void work() {
  13. System.out.println("农民在耕地");
  14. }
  15. }

现在我们回顾适用性第一条和第二条, 我们要创建一个 Factory 类, 这个类可以创建 TeacherFarmer , 但我们不知道到底创建的是 Teacher 还是 Farmer, 我们将判断创建的对象类型交给子类来判断, 那么我们需要这样一个抽象类和具体子类:

abstract class Factory{
    public abstract Worker getWorker();
}

class TeacherFactory extends Factory {
    @Override
    public Worker getWorker() {
        ...
        return new Teacher();
    }
}

class FarmerFactory extends Factory {
    @Override
    public Worker getWorker() {
        ...
        return new Farmer();
    }
}

这样我们就可以通过调用具体子类重写的 getWorker() 的方法来创建对象:

Factory factory = new TeacherFacoty();
Worker worker = factory.getWorker();

以上其实就是很多文章中提到的抽象方法模式.

也可以将抽象类换为一个自定义的新的接口, 通过接口实现类来创建, 比如:

interface Factory{
    Worker getWorker();
}

但回看实用性的第三点, “将哪一个帮助子类是代理者这一信息局部化的时候“, 也就是说不如我们直接根据要求得到一个 factory, 这个 factory 就能创建我们要的类型的 worker, 所以最好再将其封装, 外层加上一个 AbstractFacoty , 只留一个静态的方法:

class AbastractFactory{

    @FunctionalInterface
    interface WorkerFactory{
        public Worker createWorker();
    }
    static class TeacherFactory implements WorkerFactory {
        @Override
        public Worker createWorker() {
            return new Teacher();
        }
    }
    static class FarmerFactory implements WorkerFactory {
        @Override
        public Worker createWorker() {
            return new Farmer();
        }
    }

    public static WorkerFactory factory(String str) {
        switch(str) {
            case "teacher":
                return new TeacherFactory();
            case "farmer":
                return new FarmerFactory();
            default:
                break;
        }
        return null;
    }
}

这样我们就可以直接传入 "teacher" 这样的参数来得到相应的工厂, 调用工厂的 .createWorker() 方法来创建对象:

AbastractFactory.WorkerFactory workerFactory = AbastractFactory.factory("teacher");
Worker worker = workerFactory.createWorker();
worker.work(); // 输出老师在工作

4. 总结

Factory Method 模式是设计模式中应用最为广泛的模式, 在面向对象的编程中, 对象的创建工作非常简单, 对象的创建时机却很重要. Factory Method 解决的就是这个问题, 它通过面向对象的手法, 将所要创建的具体对象的创建工作延迟到了子类(或接口实现类),从而提供了一种扩展的策略, 较好的解决了这种紧耦合 (close coupling) 的关系.

参考文章