设计模式简讲程序员

13. 工厂方法模式

2018-06-29  本文已影响0人  Next_吴思成

定义

工厂方法模式(Factory Method Pattern)又称为工厂模式,也叫虚拟构造器(Virtual Constructor)模式或者多态工厂(Polymorphic Factory)模式,它属于类创建型模式。在工厂方法模式中,工厂父类负责定义创建产品对象的公共接口,而工厂子类则负责生成具体的产品对象,这样做的目的是将产品类的实例化操作延迟到工厂子类中完成,即通过工厂子类来确定究竟应该实例化哪一个具体产品类。

通俗理解

老王家里开了一家“老王杯子塑料厂”,做的是杯子。前几年生意好,杯子卖得越来越火,畅销海内外。随着市场的饱和,老王发现,他们家的杯子越来越卖不动了,不管是方形的杯子,还是圆形的杯子,亦或椭圆形的杯子,消费者越来越不买账,塑料厂的生意也因此节节败落。眼瞧着工厂都快倒闭了,敏锐的老王发现,市场上的塑料饭盒还是一片蓝海,老王为了能够让塑料厂存活下去,为了厂里面的几百人的饭碗,决定进入这个市场。

虽然这个市场前景一片大好,但是可不是想进就进。塑料饭盒和杯子的制造工艺相同却在细节上面有所偏差,例如杯子只需要简单的冲模就可以了,但是饭盒的容量更大,除了冲模之外还要加一些加强筋,那样饭盒才不容易碎掉。老王呀,为了这样的一件事情,真是愁得都变成了地中海了。

于是他和厂里的技术人员交流如何去实现。技术人员和不像老王一样天天去邻居家,还是会研究一下技术问题的。他们一眼就看透了,虽然杯子和饭盒在工艺上有偏差,但是偏差并不大,原来的机器调整一下参数,开一条生产线就可以解决了。

有生意头脑的老王,成立了一家“老王饭盒塑料厂”,按照技术人员提出的建议开干起来。这不,不到一个月,老王就拿着他新颖的饭盒,杀进了这片蓝海当中了。

这个就是工厂方法模式,在原来的工厂上面,再开一家新的工厂,新旧两家工厂的工艺是相同的,但是产不同种类的产品。同时,每个工厂都有不同的生产线,即使是同一种种类的产品,也可以在一个工厂里面生产出不同类型的产品。就像老王的厂一样,一开始只有杯子厂,杯子厂产圆形、方形的杯子。后来杯子的市场不好了,借用杯子厂的机器,开了一家饭盒厂,生产圆形的、方形的饭盒,而不是在杯子厂上生产饭盒。

示例

程序以老王的杯子厂做示例子。

渣渣程序

按照昨天学的简单工厂模式,我们可以写出下面的程序:

产品基类

public abstract class BaseProduct {
    public abstract String type();
}

杯子和饭盒

public class CircleCup extends BaseProduct {
    @Override
    public String type() {
        return "这是一个圆杯子";
    }
}

public class CircleLunchBox extends BaseProduct {
    @Override
    public String type() {
        return "这是一个圆饭盒";
    }
}

工厂

public class Factory {
    public static BaseProduct build(String type) {
        switch (type){
            case "circleCup": return new CircleCup();
            case "squareCup": return new SquareCup();
            case "circleLunchBox": return new CircleLunchBox();
            case "squareLunchBox": return new SquareLunchBox();
            default:return null;
        }
    }
}

调用方

public class Main {
    public static void main(String[] args) {
        BaseProduct cup = Factory.build("circleCup");
        System.out.println(cup.type());

        BaseProduct lunchBox = Factory.build("circleLunchBox");
        System.out.println(lunchBox.type());
    }
}

上面的程序存在以下问题:

  1. Factory的责任太大,他不仅仅要生产杯子,也要生产饭盒,如果需要生产牙刷,那么还得在Factory里面加代码,明显违反开闭原则。
  2. Factory的责任不明确,杯子生产和饭盒生产明显不是一条生产线上的东西,但是他们却在一个工厂里面生产了。

优化

既然所有的问题都是因工厂而起,那么这些问题的解决,就只能交给工厂了。工厂方法就是为了解决这个问题而生的。

类图

程序

工厂类接口IFactory

public interface IFactory {
    BaseProduct build(String type);
}

杯子工厂类

public class CupFactory implements IFactory {
    public BaseProduct build(String type) {
        switch (type){
            case "circleCup": return new CircleCup();
            case "squareCup": return new SquareCup();
            default:return null;
        }
    }
}

杯子和饭盒抽象类BaseProduct

public abstract class BaseProduct {
    public abstract String type();
}

杯子具体类

public class CircleCup extends BaseProduct {
    @Override
    public String type() {
        return "这是一个圆杯子";
    }
}

调用方

public class Main {
    public static void main(String[] args) {
        IFactory cupFactory = new CupFactory();
        BaseProduct cup = cupFactory.build("circleCup");
        System.out.println(cup.type());

        IFactory lunchBoxFactory = new LunchBoxFactory();
        BaseProduct lunchBox = lunchBoxFactory.build("circleLunchBox");
        System.out.println(lunchBox.type());
    }
}

优点

  1. 工厂不单单只有一个,可以根据基类的工厂扩展不同的工厂,用户选择工厂生产产品就可以,不需要关心生产的细节。
  2. 加入新的产品时候,不需要像原来的简单工厂一样,修改工厂方法,而是通过添加新的工厂和新的产品来解决,符合开闭原则。

缺点

  1. 加产品的时候要加产品类,还要加工厂类,类好多好庞大。

应用场景

  1. 用户不关心产品的生产过程,只知道相应的工厂就可以生产产品
  2. 需要扩展不同的工厂的情况下使用,如果使用简单工厂的时候,如果发现工厂类频繁改动,那么就可以考虑使用工厂方法模式。

扩展

基于反射和xml实现工厂方法模式

基于SpringBean实现工厂方法模式

开源代码示例

https://www.jianshu.com/p/8c0f2ee55be0

上一篇 下一篇

猜你喜欢

热点阅读