设计模式之工厂方法模式与抽象工厂模式
工厂方法模式(Factory Method): 定义一个用于创建对象的接口,让子类决定去将哪一个类实例化。Factory Method是一个类的实例化延迟到其子类。
简单地说:工厂模式就是依据需求生产不同的对象供我们使用的。
需求:造汽车。生产出不同类型的汽车如宝马、奔驰等
简单工厂模式
在说工厂模式之前,不得不提简单工单模式。首先我们依据简单工厂模式实现我们的需求。
汽车父类Car:
public class Car {
protected String carBrand() {
return null;
}
private String production() {
return "汽车开始生产啦~ ";
}
private String assemble() {
return "汽车开始组装啦~ ";
}
public void run() {
System.out.println(carBrand()+ production()+ assemble()+"汽车跑起来啦~");
}
}
奔驰:
public class Benz extends Car {
@Override
protected String carBrand() {
return "奔驰";
}
}
宝马:
public class Bmw extends Car {
@Override
protected String carBrand() {
return "宝马";
}
}
代码和例子都非常简单,不需要解释。
对外提供简单工厂方法:
public class CarSimpleFactory {
/**
* 简单工厂模式最大的优点在于工厂类中包含了必要的逻辑判断。根据条件去决定实例化的类。
* 对于客户端来说,去除了具体产品的依赖。
* 如果需要增加新的类的话,需要修改原来的代码。
*/
public static Car creatCar(String type) {
Car car = null;
switch (type) {
case "Benz":
car = new Benz();
break;
case "Bmw":
car = new Bmw();
break;
default:
break;
}
return car;
}
}
运行:
public class test {
public static void main(String[] args) {
//简单工厂
Car benz = CarSimpleFactory.creatCar("Benz");
benz.run();
Car bmw = CarSimpleFactory.creatCar("Bmw");
bmw.run();
// 奔驰汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
// 宝马汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
}
}
可以看到,如果我们需要一辆奔驰,我们在制造该对象时需要传入相应的条件。如果我们现在需要新增一辆法拉利汽车的话,我们则需要直接对CarSimpleFactory 类进行修改,这违反了开-闭原则。
那么,接下来看一下工厂方法模式针对这一缺点是如何改进的呢?
CarSimpleFactory 改为ICarFactory接口:
public interface ICarFactory {
//工厂方法的逻辑判断移到了客户端,客户端需要决定去实例化哪一个类。逻辑选择判断的问题依旧存在。从工厂类转移到了客户端。
Car creatCar();
}
汽车父类:
public abstract class Car implements ICarFactory{
abstract String carBrand();
private String production() {
return "汽车开始生产啦~ ";
}
private String assemble() {
return "汽车开始组装啦~ ";
}
public void run() {
System.out.println(carBrand() + production() + assemble() + "汽车跑起来啦~");
}
}
奔驰,子类返回一个自身对象:
public class Benz extends Car{
@Override
public Car creatCar() {
return new Benz();
}
@Override
String carBrand() {
return "奔驰";
}
}
运行:
public class test {
public static void main(String[] args) {
//简单工厂
Car benz = CarSimpleFactory.creatCar("Benz");
benz.run();
Car bmw = CarSimpleFactory.creatCar("Bmw");
bmw.run();
//工厂方法
ICarFactory benz2 = new Benz();
benz2.creatCar().run();
ICarFactory bmw2 = new Bmw();
bmw2.creatCar().run();
// 奔驰汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
// 宝马汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
}
}
可以看到:如果我们现在需要增加一辆法拉利的话,不需要对原来的代码进行修改,而是写一个法拉利子类实现ICarFactory工厂。在我们需要时,直接new一个法拉利出来就行了。
抽象工厂模式(Abstract Factory): 提供一个创建一系列相关或依赖对象的接口,而无需指定它们具体的类。
这里我选择使用配置文件加反射进行解耦。
创建一个factory.properties,指定我们需要创建的对象的类型。
carType=Benz
这个时候我们的工厂类carFactory:
public class CarFactory {
private static String carType;
private static String className = "Creational.AbstractFactory.";
private static Properties pp = new Properties();
static {
try {
pp.load(CarFactory.class.getResourceAsStream("factory.properties"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 这个时候我们需要创建不同的汽车对象时只需要修改配置文件即可。
*
* @return
*/
public static Car creatCar() {
Car car = null;
carType = pp.getProperty("carType");
try {
Class clazz = Class.forName(className + carType);
car = (Car) clazz.getConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return car;
}
}
运行:
public class test {
public static void main(String[] args) {
//简单工厂
// Car benz = CarSimpleFactory.creatCar("Benz");
// benz.run();
// Car bmw = CarSimpleFactory.creatCar("Bmw");
// bmw.run();
//
// //工厂方法
// ICarFactory benz2 = new Benz();
// benz2.creatCar().run();
// ICarFactory bmw2 = new Bmw();
// bmw2.creatCar().run();
// 奔驰汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
// 宝马汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
//抽象工厂
//根据配置文件获取类信息,进行反射创建出对象
CarFactory.creatCar().run();
// 奔驰汽车开始生产啦~ 汽车开始组装啦~ 汽车跑起来啦~
}
}
如果我们想创建一个宝马汽车对象,我们只需要把配置文件修改为:
carType=Bmw
这时候就不需要对源代码进行任何的修改了。
本文地址:http://blog.youkuaiyun.com/prodigalwang/article/details/76030272