實例:用簡單工廠實現的計算器
Ø 客戶端代碼 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<String, Object> operations =
new HashMap<String, Object>();
//構造函數,讀取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就也不用去改動了,而是依賴於配置文件中的容器的注入。