设计模式 – 简单工厂模式(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 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就也不用去改动了,而是依赖于配置文件中的容器的注入。

你可能感兴趣的:(设计模式,简单工厂模式,factory)