工厂模式

在生活中,我们用的所有东西都是通过工厂生产出来,比如:手机,汽车,电脑等。在 面向对象的世界里,对象也是可以通过工厂来创建的。今天我们就来谈论一下创建型模式--工厂设计模式。

1. 案例背景

设计模式一般比较抽象,为了方便理解,我们首先来引用一个生活中的例子-- 消费者去 汽车城或者4s 店 买汽车。这里有一下对象:1. 消费者; 2. 汽车销售方。 3. 汽车。

2. 不用设计模式

这里我们首先来分析 不使用 设计模式的情况下,代码的实现方式

  • Car 接口

生活中 汽车销售方一般是4s 店或者汽车经销商,一般都会销售不同品牌或者型号的汽车,但是具体是啥汽车我们不知道,所以设计一个Car 接口,来抽象一下汽车的型号或者品牌

public interface Car {
    /**
     * 驾驶
汽车就一个方法,被被人驾驶
     */
    void drive();
}
  • 汽车

汽车接口设计好了,接下来我们就来设计一下具体的汽车,假设 是 宝马和奥迪

public class BMWCar implements Car {
    @Override
    public void drive() {
        System.out.println("驾驶 BMW  !");
    }
}

public class AODICar implements Car {
    @Override
    public void drive() {
        System.out.println("  驾驶 奥迪  !");

    }
}
  • 汽车销售对象

汽车有了,接下来我们来设计 汽车销售对象。假设该能售卖 宝马和奥迪

public class SaleCarStore {

    public Car sale(String carName) {
        Car car = null;
      if ("BMW".equals(carName)) {//宝马汽车
          car = new BMWCar();
      }
      if ("AODI".equals(carName)) {// 奥迪汽车
          car = new AODICar();
      }
      return car;
    }
}

汽车销售方就一个方法,就是 sale 汽车。我们没有使用设计模式的情况下,一般是自己 new 对象。当然实际生活中一般都是 汽车工厂生产好汽车,交给4s 店或者其他经销商来卖。后面我们再来分析使用 汽车工厂 的好处。

  • 消费者

接下来我们只需要 设计一个 消费者对象,通过 汽车消费方去购买汽车即可。

public class CarCustomer {
    private SaleCarStore saleCarStore ;
    CarCustomer(SaleCarStore saleCarStore) {//消费者汽车售卖对象买车
        this.saleCarStore = saleCarStore;
    }

    public Car getCar(String carName) {
        Car car = saleCarStore.sale(carName);
        return car;
    }

    /**
     * 驾驶 买完车之后就 自己开车走了
     * @param car
     */
    public void drive(Car car) {
        car.drive();
    }
    public static void main(String[] args) {
        SaleCarStore saleCarStore = new SaleCarStore();
        CarCustomer carCustomer = new CarCustomer(saleCarStore );// 消费者 通过 SaleCarStore  对象买车
        Car bwm = carCustomer.getCar("BMW");// 假设购买的是 宝马
        carCustomer.drive(bwm);
    }

上面是我们在没有使用 工厂设计模式下的代码。消费者成功的购买到了汽车,并开走了。这时候,又有一个消费者要来买汽车了,但是他嫌宝马和奥迪都太贵了,要买五菱宏光,但是这时候 汽车销售对象,没有五菱宏光,但是上面的生意不可能不做吧,于是就连夜赶工 搞到了一台。于是 SaleCarStore 对象就必须要修改:

public class SaleCarStore {

    public Car sale(String carName) {
        Car car = null;
      if ("BMW".equals(carName)) {//宝马汽车
          car = new BMWCar();
      }
      if ("AODI".equals(carName)) {// 奥迪汽车
          car = new AODICar();
      }
      // add 
      if ("WLHG".equals(carName)) {// 五菱宏光
          car = new WLHGCar();
      }
      return car;
    }
}

----- 购买
public static void main(String[] args) {
        SaleCarStore car4sStore = new SaleCarStore();
        CarCustomer carCustomer = new CarCustomer(car4sStore);
        Car bwm = carCustomer.getCar("WLHG");
        carCustomer.drive(bwm);
    }

好了,钱赚到了。生意越来越好,接下来,买各种各样的车的人都有,比如 思域啊,迈锐宝XL 啊,奥迪A4L 啊等等。那么我们这时候如果在原来的基础上 满足消费者的需求就要不断 的 添加 如下类似的代码:

// add .......
      if ("WLHG".equals(carName)) {// 五菱宏光
          car = new WLHGCar();
      }
// add .......

这时候,老板就发现,自己不能再这样搞下去了,虽然钱赚到了,自己却累的要死。于是,就想到一个主意:顾客要来买车,就先下个单子,拿到这个单子以后,去联系 汽车生产厂商,然他们去生产汽车,自己中间赚差价就好了。于是,代码就可以改成下面的样子:

  • 汽车工厂--简单工厂
public class SimpleCarFactory {

    public Car createCar(String carName) {
        Car car = null;
        if ("BMW".equals(carName)) {//宝马汽车
            car = new BMWCar();
        }
        if ("AODI".equals(carName)) {// 奥迪汽车
            car = new AODICar();
        }
        if ("WLHG".equals(carName)) {// 五菱宏光
            car = new WLHGCar();
        }

        return car;
    }
}
----- SaleCarStore 
public class SaleCarStore {

    private SimpleCarFactory simpleCarFactory;
    SaleCarStore(SimpleCarFactory simpleCarFactory) {
        this.simpleCarFactory = simpleCarFactory;
    }

    public Car sale(String carName) {
//        Car car = null;
////      if ("BMW".equals(carName)) {//宝马汽车
////          car = new BMWCar();
////      }
////      if ("AODI".equals(carName)) {// 奥迪汽车
////          car = new AODICar();
////      }
////      // add
////      if ("WLHG".equals(carName)) {// 五菱宏光
////          car = new WLHGCar();
////      }
        // 简单工厂创建Car 对象
        Car car = simpleCarFactory.createCar(carName);
        return car;
    }
}
---- CarCustomer#main
 public static void main(String[] args) {
// 简单工厂
        SimpleCarFactory simpleCarFactory = new SimpleCarFactory();
        SaleCarStore saleCarStore = new SaleCarStore(simpleCarFactory);
        CarCustomer carCustomer = new CarCustomer(saleCarStore);
        Car bwm = carCustomer.getCar("WLHG");
        carCustomer.drive(bwm);
    }

好了,现在 汽车经销商老板 轻松了,不管顾客需要什么样的汽车,都可以交给 SimpleCarFactory 工厂来生产了。

注意:简单工厂模式原本是不属于常用23中设计模式中的,在《Head First》中有解释,上面的案例也是从 这本书中演变来的,书中是 披萨 案例。

  • 工厂方法

承接上一个案例,虽然顾客对汽车的需求加大,各种汽车都要满足,于是 SimpleCarFactory 汽车工厂 必须扩展自己的 createCar 方法,随着工厂规模的发展出现了以下代码:

 public Car createCar(String carName) {
        Car car = null;
        if ("BMW".equals(carName)) {//宝马汽车
            car = new BMWCar();
        }
        if ("AODI".equals(carName)) {// 奥迪汽车
            car = new AODICar();
        }
        if ("WLHG".equals(carName)) {// 五菱宏光
            car = new WLHGCar();
        }
       // add if()........
       // add if()........
       // add if()........
        return car;
    }

我们发现,要是无限添加 if ,createCar 方法会变得难以维护。作为工厂老板,就想了一个办法,把 createCar ()拆开,分成不同的生产小组,生产各自的汽车,于是 代码就变成了这样:

public class CarFactoryMethod  {

    //生产宝马
    public BMWCar createBMWCar() {
        return new BMWCar();
    }

    // 生产奥迪
    public AODICar createAODICar() {
        return new AODICar();
    }

    //生产五菱宏光
    public WLHGCar createWLHGCar() {
        return new WLHGCar();
    }
}

上面这个模式就被叫做 工厂方法。如果,现在新增一个汽车,只需要添加一个 方法,来创建即可。

  • 抽象工厂

随着工厂的发展,宝马车出现了不同的车系,如X1,X6 等,奥迪出现了 A3,A4L,A6L等,于是,宝马和奥迪工厂就独立出来了,单独生产这几种车系。

public class BMWFactoryMethod {

    public BMWCarX1 X1() {
        return new BMWCarX1();
    }

    public BMWCarX5 X5() {
        return new BMWCarX5();
    }
}

------- 奥迪车系
public class AODIFactoryMethod {

    public AODICarA3 aodiCarA3() {
        return new AODICarA3();
    }
    
    public AODICarA4L aodiCarA4L() {
        return new AODICarA4L();
    }
}

首先,要说明一个问题,抽象工厂,不是对代码的抽象,也就说 在代码里面 我们不需要将工厂 用 abstract 修饰,抽象工厂,是从 《Head First》中翻译过来的,抽象工厂 是对 工厂方法的延伸,抽象工厂可以生产 一系列相关的产品,比如 宝马系列,奥迪系列。这里就是 国内经常有人说的 产品到 产品族的概念。注意,这里为了描述简单,并没有 抽取接口,重要的是 编程思想, 我们从 工厂方法,生产单个汽车产品,到 扩展到一个工厂可以生产 一系列相关的系列汽车产品,也就是 从 工厂方法 扩展到了 抽象工厂。那么抽象 就应该是对 事物扩展的抽象了,而不是具体对 代码的抽象,并不强制你对代码进行抽象。比如,扩展宝马车系,对不可预见的车系进行抽象,因为我并不知道,下一个宝马车系是啥,但是一旦确定了,就可以直接在工厂中添加方法创建即可,所以,这里的抽象应该是对事物的抽象。

在我们明白了产品到 产品系列的概念后,可以对抽象工厂 进行接口设计。

  • CarFactory
/**
 * car 工厂定义
 */
public interface CarFactory {

    Car createCar(String type);
}

----- car 
public class BMWCarX1 implements Car {

    public BMWCarX1() {
        System.out.println("X1");
    }

    @Override
    public void drive() {
        System.out.println("drive X1");
    }
}

public class BMWCarX5 implements Car {

    public BMWCarX5() {
        System.out.println("X5");
    }

    @Override
    public void drive() {
        System.out.println("drive X5");
    }
}

------- BMWCarFactoryMethod 抽象工厂
public class BMWCarFactoryMethod implements CarFactory {
    @Override
    public Car createCar(String type) {
        switch (type) {
            case "X1":
                return bmwCarX1();
            case "X5":
                return bmwCarX5();
        }
        return null;
    }

    private BMWCarX1 bmwCarX1() {
        return new BMWCarX1();
    }
    private BMWCarX5 bmwCarX5() {
        return new BMWCarX5();
    }
}

到这里我们就分析了 工厂模式中的 简单工厂,工厂方法和抽象工厂的设计思想。我们可以发现一个问题,工厂模式是不符合 开闭原则的,但是比较符合单一职责原则,工厂模式实现方式可以有多中,不必纠结固定的实现方式。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 通过面向对象的封装,继承和多态来降低程序的耦合度。下面就让我们来深入学习这个模式。 工厂模式:客户类和工厂类分开。...
    linbj阅读 4,685评论 0 0
  • 0、序 在上一篇文章《工厂方法模式》中,我们定义了奥迪工厂AudiFactory 生产出来的就是奥迪汽车和 奔驰工...
    YotrolZ阅读 4,363评论 0 1
  • 为了防止被“杀”了祭天,学点设计模式,并总结下还是有必要的。 一:模式理解 工厂模式的作用是新建对象。 工厂模式的...
    阿菜的博客阅读 4,773评论 0 19
  • 工厂模式概述 工厂模式是设计模式的一种,从功能上来说,它的主要作用是创建对象。细分一下,有三种不同类型的工厂模式,...
    flionel阅读 3,987评论 5 3
  • 等待 也许,你等了很久 也许,你不再期待 但也许,你等的人正在来的路上 夜 在路上 与你相遇在熟悉的街...
    Msint赵客阅读 1,207评论 0 0

友情链接更多精彩内容