設計模式 – 簡單工廠模式(Factory)

實例:用簡單工廠實現的計算器

Ø  客戶端代碼 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;

    }

}

    說明:由於JAVAswitch只能對整型(intcharbytelong)和枚舉型進行判斷,因此參數沒有傳遞字符串。

    但是,策略+工廠並不是令設計達到最簡做法,更好的一種做法是利用配置文件和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就也不用去改動了,而是依賴於配置文件中的容器的注入。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章