什么是工厂模式
- 工厂模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们定义一个公共的接口。即工厂,让其生产继承某个抽象类或者接口的不同子类对象,这样只需要通过名称告诉工厂我们需要一个什么样的子类对象即可,而不需要关心其如何进行创建,从而对外隐藏对象创建的逻辑。
- 缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂或者时修改工厂类的代码。
例子:实现两个数的加减乘除运算,后续可能会添加别的运算法则,如何设计实现代码的可复用,可扩展性。
简单工厂模式
实现过程:
- 抽象接口:
package com.zzu;
/**
* 抽象运算类
*/
public interface Operation {
//运算方法,用于执行各种运算操作
public void operation(String firstNum,String secondNum);
}
- 四种运算操作,继承于Operation接口
加法:
package com.zzu;
public class AddOperation implements Operation{
@Override
public void operation(String firstNum, String secondNum) {
System.out.println("执行加法操作...");
System.out.println(firstNum + "+" + secondNum + "=" + (Integer.parseInt(firstNum)+Integer.parseInt(secondNum)));
}
}
减法:
package com.zzu;
public class SubtractionOperation implements Operation{
@Override
public void operation(String firstNum, String secondNum) {
System.out.println("执行减法操作...");
System.out.println(firstNum + "-" + secondNum + "=" + (Integer.parseInt(firstNum)-Integer.parseInt(secondNum)));
}
}
乘法:
package com.zzu;
public class multipOperation implements Operation{
@Override
public void operation(String firstNum, String secondNum) {
System.out.println("执行乘法操作...");
System.out.println(firstNum + "*" + secondNum + "=" + (Integer.parseInt(firstNum)*Integer.parseInt(secondNum)));
}
}
除法:
package com.zzu;
public class divOperation implements Operation{
@Override
public void operation(String firstNum, String secondNum) {
System.out.println("执行除法操作...");
System.out.println(firstNum + "/" + secondNum + "=" + (Integer.parseInt(firstNum)/Integer.parseInt(secondNum)));
}
}
- 工厂可以根据传入的参数生产不同的操作对象
import com.zzu.*;
public class Factory {
public static Operation getInstance(String op) {
if("+".equals(op)) {
return new AddOperation();
} else if("-".equals(op)) {
return new SubtractionOperation();
}else if("*".equals(op)) {
return new multipOperation();
} else if ("/".equals(op)) {
return new divOperation();
}
return null;
}
}
- 测试类
import com.zzu.AddOperation;
import com.zzu.Operation;
public class Test {
/*
实现11和2的四种运算操作
*/
public static void main(String[] args) {
//加法操作
Operation o1 = Factory.getInstance("+");
o1.operation("11","2");
//减法操作
Operation o2 = Factory.getInstance("-");
o2.operation("11","2");
//乘法操作
Operation o3 = Factory.getInstance("-");
o3.operation("11","2");
//除法操作
Operation o4 = Factory.getInstance("-");
o4.operation("11","2");
}
}
执行结果:
可以看出可以实现既定的目标,但是如果有需求变更,比如下载要增加一个求平方的运算,那么我们就需要改动工厂类,需要再增加一个恶else if,因此如果需求变更很大的情况下,对工厂类的变更就非常大,下面对其进行改进。
抽象工厂模式
实现过程:
改进的地方:
1、定义一个抽象工厂的接口,并在其中定义一个创建对象的抽象方法
2、定义一个类实现工厂接口,用于生产不同的实例对象
- 抽象工厂接口:
package com.zzu;
public interface AbstractFactory {
public Operation create();
}
- 生产加法操作对象的工厂:
package com.zzu.factory;
import com.zzu.AbstractFactory;
import com.zzu.AddOperation;
import com.zzu.Operation;
public class AddFactory implements AbstractFactory {
@Override
public Operation create() {
return new AddOperation();
}
}
- 生产j减法操作对象的工厂:
package com.zzu.factory;
import com.zzu.AbstractFactory;
import com.zzu.AddOperation;
import com.zzu.Operation;
import com.zzu.SubtractionOperation;
public class SubFactory implements AbstractFactory {
@Override
public Operation create() {
return new SubtractionOperation();
}
}
- 生产乘法操作对象的工厂:
package com.zzu.factory;
import com.zzu.AbstractFactory;
import com.zzu.AddOperation;
import com.zzu.Operation;
import com.zzu.multipOperation;
public class MutilFactory implements AbstractFactory {
@Override
public Operation create() {
return new multipOperation();
}
}
- 生产除法操作对象的工厂:
package com.zzu.factory;
import com.zzu.AbstractFactory;
import com.zzu.AddOperation;
import com.zzu.Operation;
import com.zzu.divOperation;
public class DivFactory implements AbstractFactory {
@Override
public Operation create() {
return new divOperation();
}
}
- 测试
import com.zzu.AbstractFactory;
import com.zzu.AddOperation;
import com.zzu.Operation;
import com.zzu.factory.AddFactory;
import com.zzu.factory.DivFactory;
import com.zzu.factory.MutilFactory;
public class Test {
/*
实现11和2的四种运算操作
*/
public static void main(String[] args) {
//加法操作
AbstractFactory addFactory = new AddFactory();
Operation o1 = addFactory.create();
o1.operation("11","2");
//减法操作
AbstractFactory subFactory = new AddFactory();
Operation o2 = subFactory.create();
o2.operation("11","2");
//乘法操作
AbstractFactory mutilFactory = new MutilFactory();
Operation o3 = mutilFactory.create();
o3.operation("11","2");
//除法操作
AbstractFactory divFactory = new DivFactory();
Operation o4 = divFactory.create();
o4.operation("11","2");
}
}
- 执行结果
也可以实现既定功能,但是其也存在一个问题,那就是每当我们要生产一个实例对象是,我们就需要创建 一个具体的实例工厂的对象,这样就造成类可能变的非常的多,其次,我们实例化一个具体的工厂时,都是使用new的方式进行,这样就写死在代码里,不利于维护,有没有可能可以通过配置文件来控制不同实例工厂的初始化?
抽象工厂+反射机制
import com.zzu.AbstractFactory;
import com.zzu.AddOperation;
import com.zzu.Operation;
import com.zzu.factory.AddFactory;
import com.zzu.factory.DivFactory;
import com.zzu.factory.MutilFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
public class Test {
/*
实现11和2的四种运算操作
*/
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException {
//String name = "com.zzu.factory.AddFactory";
Properties properties = new Properties();
InputStream in = Object.class.getResourceAsStream("/configure.properties");
//包装字节流,设置编码格式防止乱码
InputStreamReader read = new InputStreamReader(in,"UTF-8");
//加载配置文件
properties.load(read);
//获取属性值
String name = (String)properties.get("className");
//通过反射机制拿到对应的类
Class<?> c = Class.forName(name);
//获取构造器
Constructor<?> constructor = c.getConstructor();
//获取实例化对象
AbstractFactory factory = (AbstractFactory) constructor.newInstance();
//创建实例化工厂
Operation o = factory.create();
//调用工厂生产对象的方法
o.operation("11","2");
}
}