工厂模式可以分为:简单工厂模式,工厂方法模式,抽象工厂模式。
简单工厂模式就没什么好说的了,无非是所有的东西都写在一个类里面,要什么就调用什么,如果要添加新的方法也是到这类里面添加,代码很多,看起来也是很乱,就像一个大工厂,什么都在里面。扩展性很低。
而工厂方法模式,把说明的理论和生产的东西就分开一点。抽象工厂模式是工厂方法模式的升级。
说简单点,后面两种工厂模式都是java三大特征的继承和多态的具体表现,你从后面的类图中就可以很简单看到继承(接口为实现)的关系,而你在代码中就很容易看到多态的使用。
关于工厂方法模式,上次已经有详细的介绍了,本文主要是介绍抽象工厂模式。
抽象工厂模式的概念
抽象工厂模式的定义:为创建一组相关或相互依赖的对象提供一个接口,而且无需指定它们的具体类。
同时你也可以对比一下工厂方法模式的定义:为某个对象提供一个接口,而且无需指定它们的具体类。
都是子类实现接口的方法,并在子类写具体的代码。这里抽象工厂的接口类是能创建多个相关的对象,而工厂方法的接口类是只创建一个对象。
抽象工厂模式的类图:
对比工厂方法模式,你要知道它们之间的类图区别,就能理解这两种模式的区别。
工厂方法模式中也是可以有多个具体工厂,也是可以有多个抽象产品,和多个具体工厂、具体产品类。区别是在抽象工厂接口类中,能创建几个产品对象。
抽象工厂模式的工厂能创建多个相关的产品对象,而工厂方法模式的工厂只创建一个产品对象。
抽象工厂模式的优点/缺点:
1.优点
针对同一组产品创建新的生产线,只需实现那组产品的抽象工厂接口即可创建新的工厂类。
2.缺点
抽象方法模式的最大缺点就是产品族本身的扩展非常困难。如果在产品族中增加一个新的产品类型,则需要修改多个接口,并影响现已有的工厂类。
上面这句话,有些人不怎么理解,我給大家解释一下,打个比方说,你要在这个工厂创建三个对象,原本只是创建两个对象的,那么你就要在抽象方法中添加一个创建对象的方法,那么所有实现了这个接口的类都是要重新添加这个创建对象的方法,这就是对之前的工厂有影响的原因。
抽象工厂模式的应用场景
当一个对象都有相同的约束时,可以使用抽象工厂模式。
打个比方说,这个工厂的几个产品都需要经过某些共同的步骤和打上相同的商标,这一组产品可以在一个工厂里面生产,减少很多重复的代码在不同的地方都出现多次。
抽象工厂模式的实例
这里设计一个工厂生产奔驰汽车和它对应的导航仪两种产品。
实例类图
这个类图和上面的抽象工厂的类图是一样的,只是把东西具体化,代码化。
各个接口/类的代码
(1)生产奔驰的接口Benz
package P3_abstractFactory;
/**
* 奔驰产品的抽象接口
*/
public interface Benz {
void carColor();//设置颜色
void carSpeed();//设置速度
void carPrice();//设置价格
}
(2)生产车辆导航仪的接口类
package P3_abstractFactory;
/**
* 车辆导航仪的抽象产品接口类
*/
public interface CarNavigator {
void navigatorColor();//导航仪的颜色
void navigatorPrice();//导航仪的价格
}
(3)奔驰工厂的抽象接口类BanzFactory
package P3_abstractFactory;
/**
* 奔驰工厂的抽象接口
*/
public interface BanzFactory {
/**
* 创建奔驰的方法
*/
Benz createCar();
/**
* 创建导航仪的方法
*/
CarNavigator createNacigator();
}
(4)生产奔驰车辆C180和相关导航仪的具体工厂类
package P3_abstractFactory;
/**
* 生产某一个型号奔驰车辆的实际工厂
*/
public class C180Factory implements BanzFactory {
@Override
public Benz createCar() {
return new BenzC180();
}
@Override
public CarNavigator createNacigator() {
return new C180Navigator();
}
}
(5)生产奔驰车辆Z260和相关导航仪的具体工厂类
package P3_abstractFactory;
/**
* 生产某一个型号奔驰车E260辆的实际工厂
*/
public class E260Factory implements BanzFactory {
@Override
public Benz createCar() {
return new BenzE260();
}
@Override
public CarNavigator createNacigator() {
return new E260Navigator();
}
}
(6)生产奔驰车辆C180的具体产品类
package P3_abstractFactory;
/**
* 奔驰C180的生产的具体类
*/
public class BenzC180 implements Benz {
/**
* 构造方法,创建的时候就设置基本属性
*/
public BenzC180() {
carColor();
carPrice();
carSpeed();
}
@Override
public void carColor() {
System.out.println("奔驰C180的颜色是银白色");
}
@Override
public void carSpeed() {
System.out.println("奔驰C180的速度是200公里每小时");
}
@Override
public void carPrice() {
System.out.println("奔驰C180的价格是100万");
}
}
(7)生产奔驰车辆C180对应导航仪的具体产品类
package P3_abstractFactory;
/**
* 车型C180的导航仪
*/
public class C180Navigator implements CarNavigator {
C180Navigator(){
navigatorColor();
navigatorPrice();
}
@Override
public void navigatorColor() {
System.out.println("汽车C180的导航仪颜色:黑色");
}
@Override
public void navigatorPrice() {
System.out.println("汽车C180的导航仪价格:480元");
}
}
(8)生产奔驰车辆E260的具体产品类
package P3_abstractFactory;
/**
* 奔驰E260的生产的具体类
*/
public class BenzE260 implements Benz {
/**
* 构造方法,创建的时候就设置基本属性
*/
public BenzE260() {
carColor();
carPrice();
carSpeed();
}
@Override
public void carColor() {
System.out.println("奔驰E260的颜色是银白色");
}
@Override
public void carSpeed() {
System.out.println("奔驰E260的速度是200公里每小时");
}
@Override
public void carPrice() {
System.out.println("奔驰E260的价格是100万");
}
}
(7)生产奔驰车辆E260对应导航仪的具体产品类
package P3_abstractFactory;
/**
* 车型E260的导航仪
*/
public class E260Navigator implements CarNavigator {
E260Navigator(){
navigatorColor();
navigatorPrice();
}
@Override
public void navigatorColor() {
System.out.println("汽车E260的导航仪颜色:白色");
}
@Override
public void navigatorPrice() {
System.out.println("汽车E260的导航仪价格:880元");
}
}
生产奔驰车辆和相关产品的调用者类AbstractFactoryDemo
package P3_abstractFactory;
/**
* 抽象工厂模式调用
* 生产两个奔驰车C180、E260和它们对应的导航仪的演示
* 这里使用多态的方法类创建各个类别的车型产品
*/
public class AbstractFactoryDemo {
public static void main(String[] a) {
System.out.println("生产奔驰车C180");
//父类但对象子类的实例
BanzFactory banzFactory = new C180Factory();//创建一个C180工厂
//调用父类的方法,这就是java多态的一种体现
banzFactory.createCar();//C180工厂生产车辆C180
banzFactory.createNacigator();//生产车辆C180对应的导航仪
System.out.println("=========================================");
System.out.println("生产奔驰车Z260");
BanzFactory banzFactory2 = new E260Factory();
banzFactory2.createCar();//E260工厂生产车辆E260
banzFactory2.createNacigator();//生产车辆E260对应的导航仪
}
}
程序运行的结果:
从实例中分析,工厂方法模式的优点/缺点
1.优点
如果需要生产新的汽车产品和对应的导航仪设备,你只需要创建一个该产品对应的具体工厂和该产品的具体实现类,不需要改变抽象的工厂类和抽象的产品类,具体工厂类和具体产品类需要什么操作已经在抽象接口类定义好了。
2.缺点
之前有说工厂方法的扩展性算是比较好的,而抽象工厂模式的扩展性就没那么好了。
比如说某个工厂需要多创建几个产品对象,那么就需要增加抽象工厂的方法,增加抽象接口的方法后,其他实现了抽象工厂接口方法的所有类都需要改变,才能正常编译。