您的位置:首页 > 移动开发 > Android开发

Android 内功心法(1.2)——android常用设计模式之工厂模式

2016-05-04 20:57 543 查看
上一篇:Android 内功心法(1.1)—android常用设计模式之单例模式 中 我阐述了几种单例模式以及现在最好的单例模式实现方法,其中包括经典单例写法和java5之后的最佳写法。

今天就要来说说工厂模式了。

工厂负责将大量有共同接口的类实例化。工厂模式可以决定将哪一个类实例化,不必事先知道每次要实例化哪一个类。

工厂模式的使用有很多种,简单工厂(静态工厂),工厂方法,抽象工厂,工厂+策略。

今天我会一一阐述。

1,简单工厂

/**
* 简单工厂模式的基类
*/
public  class Operation {

private double numberA;//算法的第一个值
private double numberB;//算法的第二个值

public double getNumberA() {
return numberA;
}

public void setNumberA(double numberA) {
this.numberA = numberA;
}

public double getNumberB() {
return numberB;
}

public void setNumberB(double numberB) {
this.numberB = numberB;
}

/**运算结果调用该方法
* @return 简单工厂处理加减乘除的运算,返回相应的结果
*/
public double getResult(){
return 0;
}
}


这是简单工厂模式的基类,一切拓展或者需要处理的类都要依赖于它。

/**
* 加法
*/
public class OperationAdd extends Operation {

/**重写算法结果
* @return
*/
@Override
public double getResult() {
return getNumberA()+getNumberB();
}
}

/**
* 减法
*/
public class OperationSub extends Operation {

/**重写算法结果
* @return
*/
@Override
public double getResult() {
return getNumberA()-getNumberB();
}
}

/**
* 乘法
*/
public class OperationMul extends Operation {

/**重写算法结果
* @return
*/
@Override
public double getResult() {
return getNumberA()*getNumberB();
}
}

/**
* 除法
*/
public class OperationDiv extends Operation {

/**重写算法结果
* @return
*/
@Override
public double getResult() {
if(getNumberB()==0)return 0;
return getNumberA()/getNumberB();
}
}


加减乘除是四个类,我只是统一写在代码块里面,并不代表这四个类在一起

加减乘除这四个类都继承了简单工厂的基类。也就是拥有两个参数的get/set方法和运算结果方法的Operation类。

/**
* 具体操作工厂的类
*/
public class OperationFactory {
public static Operation createOperation(String operate) {

Operation operation;
switch (operate) {
case "+":
operation = new OperationAdd();
break;
case "-":
operation = new OperationSub();
break;
case "*":
operation = new OperationMul();
break;
case "/":
operation = new OperationDiv();
break;
default:
operation = null;
break;
}
return operation;
}
}


这个类的作用就是处理逻辑。根据用户输入的符号(+-*/)来处理相对应的逻辑。

/**
* 简单工厂模式的测试类
*/
public class OperationTest {
/**简单工厂模式说明:
* 一个总代理类,
* 确定好参数,传入,传出。
* 确定好使用到的方法,以便子类重写
*
* 所有实现具体算法的类都要继承这个代理类
* 内部实现具体的算法
* 按照设计模式的四大原则,必须实现父类的全部方法
*
* 提供一个供外部调用的类
* 外部传入参数,这个类根据参数的不同获取不懂的算法,得到不懂的结果
* 而方法的多少是根据之前写好的实现类而定
* */
private Operation operation;

public void testAdd() {//+
operation = OperationFactory.createOperation("+");
operation.setNumberA(1);
operation.setNumberB(2);
Log.e("test", "简单工厂模式运算结果(+):" + operation.getResult());
}

public void testDiv() {///
operation = OperationFactory.createOperation("/");
operation.setNumberA(1);
operation.setNumberB(2);
Log.e("test", "简单工厂模式运算结果(/):" + operation.getResult());
}

public void testMul() {//*
operation = OperationFactory.createOperation("*");
operation.setNumberA(1);
operation.setNumberB(2);
Log.e("test", "简单工厂模式运算结果(*):" + operation.getResult());
}

public void testSub() {//-
operation = OperationFactory.createOperation("-");
operation.setNumberA(1);
operation.setNumberB(2);
Log.e("test", "简单工厂模式运算结果(-):" + operation.getResult());
}
}


根据这个加减乘除的小栗子可以看出简单工厂模式的好处。

如果不用简单工厂模式,那么你需要实现四个逻辑,重复大量代码。后期的拓展和维护都不好做。

而是用简单工厂模式处理后的代码可以看出,逻辑清晰。若想要增加某个新功能,比如模运算,那么我们只需要新建一个OperationMi类添加如下代码:

/**
* 模运算
*/
public class OperationMi extends Operation {

/**重写算法结果
* @return
*/
@Override
public double getResult() {
return getNumberA()%getNumberB();
}
}


这样,“新功能”写完了。新功能没有影响原来的任何一个功能也没有使工厂的基类改变。

而是用新功能则只需要在Operation里的switch方法中加入:

case "%":
operation = new OperationMi();
break;


怎么样?是不是拓展性很好,而且遵循了设计模式的“最少知道原则”。

类于类之间根本没有互相通讯

这就是简单工厂或者叫静态工厂模式。写起来很简单,使用起来很方便的一个设计模式。

不过,这种设计模式也有它的缺点在里面。也常常被否定为经典24种设计模式中的一种。

它的缺点就是没有遵循“开闭原则”。对拓展开放做到了,但是没有对修改关闭。

每当添加一种工厂的时候就要在OperationFactory类中createOperation方法中添加一个case方法。

这就已经修改了代码。所以,简单工厂模式应该不符合设计模式的“要求”。

那么,简单工厂还可以进一步的进行优化。

接下来的代码是把简单工厂和策略模式混合运用。算是对简单工厂的用法进一步的优化。

2,简单工厂+策略

借用简单工厂的代码,并加以稍微的修改:

将简单工厂的基类换成策略模式的基类。

/*
* 策略模式的基类
*/
public abstract class Strategy {
/**定义所有支持算法的公共接口*/

private double numberA;//算法的第一个值
private double numberB;//算法的第二个值

public double getNumberA() {
return numberA;
}

public void setNumberA(double numberA) {
this.numberA = numberA;
}

public double getNumberB() {
return numberB;
}

public void setNumberB(double numberB) {
this.numberB = numberB;
}

/**
* 算法方法
*/
public abstract double GetResultInterface(double a,double b);
}


可以看出,它是一个抽象类。

修改操作简单工厂的类为:

public class ConcreteStrategy {
/**策略模式+简单工厂模式
* 相当于用策略模式把工厂模式的调用方法简化
* 传入相应的值,就会得到相应的方法。
* 获得该算法以后
* 通过公用的接口得到算法结果或者自定义的想要的结果
* */
private Strategy strategy;

/**
* 初始化传入具体的策略对象
*
* @param i 算法要求:加减乘除
*/
public ConcreteStrategy(String i) {
switch (i) {
default:
case "+":
strategy=new ConcreteStrategyA("+");
break;
case "-":
strategy=new ConcreteStrategyB("-");
break;
case "*":
strategy=new ConcreteStrategyC("*");
break;
case "/":
strategy=new ConcreteStrategyD("/");
break;
}
}

/**
* 上下文的接口,根据具体的策略对象调用其算法方法
*/
public void contextInterface(double a,double b) {
strategy.GetResultInterface(a,b);
}
}


算法逻辑实现类

/*
*加法类
*/
public class ConcreteStrategyA extends Strategy {

private String status;

public ConcreteStrategyA(String status) {
this.status= status;
}

/**
* 算法A的实现
*/
@Override
public double GetResultInterface(double a,double b) {
if(status.equals("+"))
return a+b;
return 0;
}
}


接下来是策略的具体实现类:

public class StrategyTest {
private ConcreteStrategy concreteStrategy;

/**选择计算模式
* @param i
*/
public void StrategyTest(String i) {
concreteStrategy = new ConcreteStrategy(i);
}

/**输入金额
* @param money
*/
public void getResult(double a,double b) {
concreteStrategy.contextInterface(a,b);
}
}


简单工厂+策略模式能够让简单工厂更加的灵活。不需要创建和实例化多个类。想要得到一个结果只需要new出一个ConcreteStrategy对象,传入想到对应的计算模式,再调用contextInterface方法,传入需要计算的值就可以得到想要的结果。

我们来比较一下:

简单工厂

operation = OperationFactory.createOperation("-");
operation.setNumberA(1);
operation.setNumberB(2);
operation.getResult();//得到结果


简单工厂+策略

concreteStrategy = new ConcreteStrategy("+");
concreteStrategy.contextInterface(1,2);//得到结果


通过代码就一目了然。

简单工厂+策略模式的代码比单纯的简单工厂模式要简单的很多。

这就是通过模式的组合运用来达到简化代码的方式。

那么,接下来这种工厂就能够弥补简单工厂的缺点。

3,工厂方法模式

借用

上面简单工厂的代码接着写

首先写一个工厂方法类的接口

public interface IFactory {

//创建工厂的抽象类
Operation createOperation();
}


再来写一个运算法则的具体工厂类

* 算法加减乘除
*/
public class ConcreteFactoryA implements IFactory {

//加法类工厂

@Override
public Operation createOperation() {
return new OperationAdd();
}
}

public class ConcreteFactoryB implements IFactory {

//减法类工厂

@Override
public Operation createOperation() {
return new OperationSub();
}
}

public class ConcreteFactoryC implements IFactory {

//乘法类工厂

@Override
public Operation createOperation() {
return new OperationMul();
}
}

public class ConcreteFactoryD implements IFactory {

//除法类工厂

@Override
public Operation createOperation() {
return new OperationDiv();
}
}


加上上面简单工厂的基类Operation和逻辑类OperationAdd等

就组成了工厂方法类。

使用方法:

private void testAdd() {
IFactory iFactory = new ConcreteFactoryA();//实例化工厂加法
Operation operation = iFactory.createOperation();//获得加法逻辑类的实例
operation.setNumberA(1);
operation.setNumberB(2);
operation.getResult();
}


这样一来。添加逻辑类就添加:

public class OperationMi extends Operation {

/**重写算法结果
* @return
*/
@Override
public double getResult() {
return getNumberA()%getNumberB();
}
}


再添加模运算的工厂类:

public class ConcreteFactoryE implements IFactory {

//加法类工厂

@Override
public Operation createOperation() {
return new OperationMi();
}
}


这样看起来是不是就成就了两个设计模式的原则。“最少知道原则”和“开闭原则”。

“最少知道原则”在简单工厂里就已经实现了。而“开闭原则”则利用工厂接口和工厂类实现了。

这样,即便最后添加了新的逻辑运算也不用去修改代码,而是相对应的添加一个新逻辑的具体工厂类。

工厂方法模式是定义一个用于创建对iangd接口让子类去决定实例化哪一个类。

当然,看懂了“简单工厂+策略模式”的程序员们也自然能够做出“工厂方法+策略”的组合代码。

通常在面对较大改动。需要添加很多的工厂以及方法类的时候,显然我们不可能一个方法一个类的去添加。

这时候 我们就需要一种更加简单方便的方法。

3,抽象工厂模式

因为抽象工厂的实现比较麻烦,代码量比较多,所以特意拿出一章来写抽象工厂。

需要看抽象工厂的程序员们可以看我的下一篇连载。

Android 内功心法(1.2.1)——android常用设计模式之工厂模式后续抽象工厂模式
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: