「补课」进行时:设计模式(2)——通过一个超级汽车工厂来了解工厂模式

「补课」进行时:设计模式(2)——通过一个超级汽车工厂来了解工厂模式1 超级汽车工厂 汽车相信大家都不陌生 我们现在最常用的交通工具得益于在奔驰在 1885 年研制的第一辆 三轮车 就是下面这个家伙 今天我来试一下使用程序通过汽车工厂来造汽车 1 1 定义一辆汽车 public interface Car void name void drive

大家好,我是讯享网,很高兴认识大家。


讯享网

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. 工厂模式扩展——多个工厂类

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

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

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

小讯
上一篇 2025-03-14 12:02
下一篇 2025-03-05 21:31

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/59110.html