实例:用简单工厂实现的计算器
Ø 客户端代码 Main.java
package com.yilong.calculator.factory;
public class Main {
public static void main(String[] args) {
Operation oper = OperationFactory.create('/');
if(oper != null) {
oper.setNumber1(23.3);
oper.setNumber2(0);
System.out.println(oper.getResult());
} else {
System.out.println("运算符非法!");
}
}
}
Ø Operation运算类Operation.java
package com.yilong.calculator.factory;
public abstract class Operation {
private double number1;
private double number2;
public abstract double getResult();
public double getNumber1() {
return number1;
}
public void setNumber1(double number1) {
this.number1 = number1;
}
public double getNumber2() {
return number2;
}
public void setNumber2(double number2) {
this.number2 = number2;
}
}
Ø 加法运算类 AddOperation.java
package com.yilong.calculator.factory;
public class AddOperation extends Operation {
@Override
public double getResult() {
return this.getNumber1() + this.getNumber2();
}
}
Ø 减法运算类 SubOperation.java
package com.yilong.calculator.factory;
public class SubOperation extends Operation {
@Override
public double getResult() {
return this.getNumber1() - this.getNumber2();
}
}
Ø 乘法运算类 MulOperation.java
package com.yilong.calculator.factory;
public class MulOperation extends Operation {
@Override
public double getResult() {
return this.getNumber1() * this.getNumber2();
}
}
Ø 除法运算类DivOperation.java
package com.yilong.calculator.factory;
public class DivOperation extends Operation {
@Override
public double getResult() {
double result = 0;
try {
result = this.getNumber1() / this.getNumber2();
} catch(Exception e) {
System.out.println("除数不能为0!");
System.exit(0);
}
return result;
}
}
Ø 运算生产工厂类 OperationFactory.java
package com.yilong.calculator.factory;
public class OperationFactory {
public static Operation create(char oper) {
Operation operation = null;
switch(oper) {
case '+':
operation = new AddOperation();
break;
case '-':
operation = new SubOperation();
break;
case '*':
operation = new MulOperation();
break;
case '/':
operation = new DivOperation();
break;
}
return operation;
}
}
说明:由于JAVA的switch只能对整型(int、char、byte、long)和枚举型进行判断,因此参数没有传递字符串。
但是,策略+工厂并不是令设计达到最简做法,更好的一种做法是利用配置文件和JAVA的反射机制来实现IOC,下面是具体做法:
Ø 文件ApplicationContext.java。主要用来定义读取配置文件的接口,例如下
次要把xml换成properties配置,一样可以实现该接口,然后主要的业务逻辑中依然可以调用getOperation方法获得运算规则。
package com.yilong.calculator.factory;
public interface ApplicationContext {
public Object getOperation(String operationKey);
}
Ø 文件ClassPathXmlApplicationContext.java
package com.yilong.calculator.factory;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
public class ClassPathXmlApplicationContext implements
ApplicationContext {
//定义装载运算规则的容器operations
private Map operations =
new HashMap();
//构造函数,读取xml配置文件,将运算类operation保存在容器里。此处还可以提供一
//个空的构造函数,表示默认情况,即默认读取某个配置文件operations.xml
public ClassPathXmlApplicationContext(String operationxml) {
try {//参数operationxml表示xml配置文件的名字,主要是提供灵活性。
SAXBuilder saxb = new SAXBuilder();
Document doc = saxb.build(this.getClass().getClassLoader().
getResourceAsStream(operationxml));
Element root = doc.getRootElement();
List list = root.getChildren("operation");
for (int i = 0; i < list.size(); i++) {
Element element = (Element) list.get(i);
String id = element.getAttributeValue("id");
String clazz = element.getAttributeValue("class");
Object operationClass =
Class.forName(clazz).newInstance();
operations.put(id, operationClass);
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Object getOperation(String operationKey) {
return operations.get(operationKey);
}
}
Ø 文件Main.java
package com.yilong.calculator.factory;
public class Main {
public static void main(String[] args) {
Operation oper = OperationFactory.create("+");
if(oper != null) {
oper.setNumber1(23.3);
oper.setNumber2(120);
System.out.println(oper.getResult());
} else {
System.out.println("运算符非法!");
}
}
}
Ø 文件OperationFactory.java
package com.yilong.calculator.factory;
public class OperationFactory {
public static Operation create(String oper) {
ApplicationContext applicationContext = new
ClassPathXmlApplicationContext("operations.xml");
return (Operation)applicationContext.getOperation(oper);
}
}
Ø 配置文件operations.xml
<operations>
<operation id="+" class="com.yilong.calculator.factory.AddOperation">
operation>
<operation id="-" class="com.yilong.calculator.factory.SubOperation">
operation>
<operation id="*" class="com.yilong.calculator.factory.MulOperation">
operation>
<operation id="/" class="com.yilong.calculator.factory.DivOperation">
operation>
operations>
注:剩下的类与前面的相同。
通过添加配置文件, OperationFactory就也不用去改动了,而是依赖于配置文件中的容器的注入。