通过两张图简单解释一下什么是简单工厂模式、工厂模式、抽象工厂模式
简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,但不属于23种GOF设计模式之一。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。
抽象工厂模式(Abstract Factory),提供一个创建一系列相关或多个相互依赖对象的接口,而无需指定它们具体的类。
开闭原则,在面向对象编程领域中,规定“软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的”,这意味着一个实体是允许在不改变它的源代码的前提下变更它的行为。
PS:增加函数是扩展,增加case是修改
简单工厂模式由于是一个工厂对象决定创建出哪一种产品类的实例,灵活性较高,但违反了开闭原则(每次修改都涉及switch语句)
工厂模式在简单工厂模式基础上符合开闭原则,但灵活度变低
为了适应多产品,在工厂模式的基础上抽象工厂模式应运而生,符合开闭原则,但灵活度依然低
于是将简单工厂模式和抽象工厂模式结合起来,结合两者特点,诞生了改进版抽象工厂(简单+抽象),符合单一职责、不符合开闭原则、灵活性高
工厂方法与抽象工厂区别的总结:
工厂方法模式:
一个抽象产品类,可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类只能创建一个具体产品类的实例。
抽象工厂模式:
多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
一个抽象工厂类,可以派生出多个具体工厂类。
每个具体工厂类可以创建多个具体产品类的实例。
区别:
工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。
工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个
简单工厂模式和改进版抽象工厂(简单+抽象)都存在不符合开闭原则的问题,而依赖注入(Dependency Injection, DI)是一种设计模式,也是Spring框架的核心概念之一。其作用是去除Java类之间的依赖关系,实现松耦合,以便于开发测试。
加反射和配置文件可以解决不符合开闭原则问题。
abstract class Benz {
abstract void createCar();
}
public class GasBenz extends Benz{
@Override
void createCar() {
System.out.println("生产燃油的Benz");
}
}
public class ElectricBenz extends Benz{
@Override
void createCar() {
System.out.println("生产电力的Benz");
}
}
abstract class BYD {
abstract void createCar();
}
public class GasBYD extends BYD {
@Override
void createCar() {
System.out.println("生产燃油的BYD");
}
}
public class ElectricBYD extends BYD{
@Override
void createCar() {
System.out.println("生产电力的BYD");
}
}
public class Car_making {
public static Benz createBenz() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
InputStream is = Car_making.class.getClassLoader().getResourceAsStream("Brands.properties");
Properties proper = new Properties();
proper.load(is);
String type = proper.getProperty("type");
String className = "abstractFactory" + "." + type + "Benz";
return (Benz) Class.forName(className).newInstance();
}
public static BYD createBYD() throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
InputStream is = Car_making.class.getClassLoader().getResourceAsStream("Brands.properties");
Properties proper = new Properties();
proper.load(is);
String type = proper.getProperty("type");
String className = "abstractFactory" + "." + type + "BYD";
return (BYD) Class.forName(className).newInstance();
}
}
//测试类
public class Test {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
Benz benz = Car_making.createBenz();
benz.createCar();
System.out.println("------------------");
BYD byd = Car_making.createBYD();
byd.createCar();
}
}
//配置文件
type = Electric