「补课」进行时:设计模式(2)——通过一个超级汽车工厂来了解工厂模式
共 3791字,需浏览 8分钟
·
2020-10-25 21:19
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 createCar(Class clazz) ;
}
这里使用泛型首先定义了泛型 T 是 Car 的子类,限制了 T 的类型,其次是输入参数必须是 Class 类型。
1.4 汽车创建工厂
接下来,我们定义一个实际的汽车创建工厂:
public class CarFactory extends AbstractCarFactory {
@Override
public T createCar(Class 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 createProduct(Class clazz) ;
}
2.4 具体工厂类
public class ConcreteCreator extends Creator {
@Override
public T createProduct(Class clazz) {
Product product = null;
try {
product = (Product) Class.forName(clazz.getName()).newInstance();
} catch (Exception e) {
// 异常处理
}
return (T) product;
}
}
具体如何产生一个产品的对象的实现,是由具体的工厂类进行实现的,具体的工厂类可以有多个,用于实现多条产品线的生产。
2.5 优点
良好的封装性,代码结构清晰。 良好的扩展性。如果我们需要增加产品类,只需要修改具体的工厂类或者扩展一个新的具体工厂类即可。 屏蔽产品类。工厂模式是点型的解耦框架,高层次的模块只需要知道产品的抽象类,其他的实现类都不需要关心。
3. 工厂模式扩展——多个工厂类
前面说工厂模式可以有多个具体工厂,如果项目复杂度足够高,将所有的产品都放在一个工厂类中做初始化有点不够清晰,那么我们可以实现多个工厂类,由每一个工厂类对应不同的业务规则做对应的产品类的初始化操作。
我如果把上面的那个超级汽车工厂改成多工厂类,先画一个类图:
这个代码我就不写了,和上面的差不多,就是从原来的一个工厂生产三种车变成了三个专属工厂生产三种车。