zoukankan      html  css  js  c++  java
  • 「补课」进行时:设计模式(2)——通过一个超级汽车工厂来了解工厂模式

    1. 超级汽车工厂

    汽车相信大家都不陌生,我们现在最常用的交通工具得益于在奔驰在 1885 年研制的第一辆「三轮车」,就是下面这个家伙:

    今天我来试一下使用程序通过汽车工厂来造汽车。

    1.1 定义一辆汽车

    public interface Car {
        void name();
        void drive();
    }
    

    身为一辆汽车,首先要有自己的名字,其次是要能开,有了这两个东西,基本上就能叫一辆汽车了。

    1.2 定义一辆特斯拉、一辆奔驰、一辆奥迪

    public class Tesla implements Car {
        @Override
        public void name() {
            System.out.println("我是特斯拉!!!");
        }
    
        @Override
        public void drive() {
            System.out.println("我是特斯拉,速度贼快!!!");
        }
    }
    
    public class Benz implements Car {
        @Override
        public void name() {
            System.out.println("我是奔驰!!!");
        }
    
        @Override
        public void drive() {
            System.out.println("我是奔驰,内饰豪华!!!");
        }
    }
    
    public class Audi implements Car {
        @Override
        public void name() {
            System.out.println("我是奥迪!!!");
        }
    
        @Override
        public void drive() {
            System.out.println("我是奥迪,科技感十足!!!");
        }
    }
    

    这里定义了三辆汽车,分别实现了他们的父亲的两个方法。

    1.3 定义抽象汽车工厂

    身为一个超级汽车工厂,当然是要能造汽车,我们创建汽车的时候,肯定是希望直接告诉工厂,我要造一辆特斯拉还是造一辆奥迪。

    如果是使用特斯拉或者是奥迪作为输入参数,那么创建的方法我们就需要分别写 3 个了,在 Java 中,这里可以使用泛型来作为输入参数,控制参数的输入类型。

    public abstract class AbstractCarFactory {
        public abstract  <T extends Car> T createCar(Class<T> clazz);
    }
    

    这里使用泛型首先定义了泛型 T 是 Car 的子类,限制了 T 的类型,其次是输入参数必须是 Class 类型。

    1.4 汽车创建工厂

    接下来,我们定义一个实际的汽车创建工厂:

    public class CarFactory extends AbstractCarFactory {
        @Override
        public <T extends Car> T createCar(Class<T> clazz) {
            Car car = null;
            try {
                car = (T)Class.forName(clazz.getName()).newInstance();
            } catch (Exception e) {
                System.out.println("汽车生产出错啦,请回炉重造!");
            }
            return (T) car;
        }
    }
    

    1.5 开始生产汽车

    public class Test {
        public static void main(String[] args) {
            AbstractCarFactory carFactory = new CarFactory();
            System.out.println("-- 第一辆车生产特斯拉 --");
            Car tesla = carFactory.createCar(Tesla.class);
            tesla.name();
            tesla.drive();
    
            System.out.println("-- 第二辆车生产奔驰 --");
            Car benz = carFactory.createCar(Benz.class);
            benz.name();
            benz.drive();
    
            System.out.println("-- 第三辆车生产奥迪 --");
            Car audi = carFactory.createCar(Audi.class);
            audi.name();
            audi.drive();
        }
    }
    

    生产的结果如下:

    -- 第一辆车生产特斯拉 --
    我是特斯拉!!!
    我是特斯拉,速度贼快!!!
    -- 第二辆车生产奔驰 --
    我是奔驰!!!
    我是奔驰,内饰豪华!!!
    -- 第三辆车生产奥迪 --
    我是奥迪!!!
    我是奥迪,科技感十足!!!
    

    2. 工厂模式

    首先是工厂模式的定义:

    Define an interface for creating an object,but let subclasses decide whichclass to instantiate.Factory Method lets a class defer instantiation tosubclasses.(定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。)

    下面是一个通用类图:

    • Product: 用于定义产品特性,实现对事物最抽象的定义,就像上面定义的 Car 。
    • ConcreteProduct: 具体对产品定义的实现,就上上面定义的特斯拉和奥迪。
    • Creator: 抽象工厂,用于最抽象对 Product 的构造的定义。
    • ConcreteCreator: Creator 的具体实现,具体实现如何创建产品类。

    2.1 抽象产品类

    public abstract class Product {
        public void method1() {
    
        }
        public abstract void method2();
    }
    

    2.2 具体产品类

    public class ConcreteProduct1 extends Product {
        @Override
        public void method2() {
    
        }
    }
    
    public class ConcreteProduct2 extends Product {
        @Override
        public void method2() {
    
        }
    }
    

    具体的产品类可以有多个,都继承于抽象的产品类。

    2.3 抽象工厂类

    public abstract class Creator {
        public abstract <T extends Product> T createProduct(Class<T> clazz);
    }
    

    2.4 具体工厂类

    public class ConcreteCreator extends Creator {
        @Override
        public <T extends Product> T createProduct(Class<T> clazz) {
            Product product = null;
            try {
                product = (Product) Class.forName(clazz.getName()).newInstance();
            } catch (Exception e) {
                // 异常处理
            }
            return (T) product;
        }
    }
    

    具体如何产生一个产品的对象的实现,是由具体的工厂类进行实现的,具体的工厂类可以有多个,用于实现多条产品线的生产。

    2.5 优点

    • 良好的封装性,代码结构清晰。
    • 良好的扩展性。如果我们需要增加产品类,只需要修改具体的工厂类或者扩展一个新的具体工厂类即可。
    • 屏蔽产品类。工厂模式是点型的解耦框架,高层次的模块只需要知道产品的抽象类,其他的实现类都不需要关心。

    3. 工厂模式扩展——多个工厂类

    前面说工厂模式可以有多个具体工厂,如果项目复杂度足够高,将所有的产品都放在一个工厂类中做初始化有点不够清晰,那么我们可以实现多个工厂类,由每一个工厂类对应不同的业务规则做对应的产品类的初始化操作。

    我如果把上面的那个超级汽车工厂改成多工厂类,先画一个类图:

    这个代码我就不写了,和上面的差不多,就是从原来的一个工厂生产三种车变成了三个专属工厂生产三种车。

  • 相关阅读:
    [搬运] Tina R329 swupdate OTA 步骤
    摄像头 ISP 调试的经验之谈(以全志 AW hawkview 为例)
    2021 年了 在 WSL2 中使用 adb 、fastboot 的等命令
    wsl2 编译 linux openwrt 项目的时候,经常会出现 bash: -c: line 0: syntax error near unexpected token `('
    sipeed v833 硬件验证以及开发记录(2021年5月18日)
    Allwinner & Arm 中国 & Sipeed 开源硬件 R329 SDK 上手编译与烧录!
    把 R329 改到 ext4 sdcard 启动变成 Read-Only 系统,导致没有文件修改权限后如何修复。
    linux kernel version magic 不一致导致的模块 加载 (insmod) 不上
    剑指 Offer 17. 打印从1到最大的n位数
    剑指 Offer 16. 数值的整数次方
  • 原文地址:https://www.cnblogs.com/babycomeon/p/13856006.html
Copyright © 2011-2022 走看看