简单工厂模式
需要实例化谁,以后可能会添加实例化的对象,就要用一个单独的类来做这个创造实例的过程,就是工厂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| public class Operation { public static double getResult(double numberA, double numberB, String operation){ double ans = 0; switch (operation) { case "+": ans = numberA + numberB; break; case "-": ans = numberA - numberB; break; case "*": ans = numberA * numberB; break; case "/": ans = numberA / numberB; break; default: System.out.println("not support operation"); break; } return ans; } }
|
问题:
- 如果需要增加函数,就需要添加新的
case
,有可能会改变原有的函数;
- 如果代码只需要调用除法,却需要编译其他的加,减,乘函数
解决办法:
实现一个运算抽象类,都有一个方法getResult()
,用来得到结果.然后加减乘除都写成运算类的子类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| public abstract class Operation { public double getResult(double numberA, double numberB){ return 0d; } }
public class Add extends Operation{ public double getResult(double numberA, double numberB){ return numberA + numberB; } }
public class Sub extends Operation{ public double getResult(double numberA, double numberB){ return numberA - numberB; } }
public class Mul extends Operation{ public double getResult(double numberA, double numberB){ return numberA * numberB; } }
public class Div extends Operation{ public double getResult(double numberA, double numberB){ if (numberB == 0){ System.out.println("除数不能为0"); throw new ArithmeticException(); } return numberA / numberB; } }
public class OperationFactory { public static Operation createOperation(String opertaion){ Operation oper = null; switch (opertaion) { case "+": oper = new Add(); break; case "-": oper = new Sub(); break; case "*": oper = new Mul(); break; case "/": oper = new Div(); break; default: System.out.println("we didnt implement this operation"); break; } return oper; } }
Operation oper = OperationFactory.createOperation(flag); double ans = oper.getResult(a, b);
|

三个角色:
- 抽象类: 定义所有支持算法的公共接口,比如运算抽象类
- 具体算法类: 具体的算法,比如加减乘除运算类
- 简单工厂类: 用来维护对运算类的应用
- 可以将类类比为产品,使用者在不清楚类生产的具体过程的情况下,可以使用不同的产品.
策略模式
定义算法家族,分别封装,让他们之间可以相互替换.这样可以保证算法的变化不会影响到客户
一系列算法都完成相同的工作,只是实现不同,可以以相同的方式调用所有的算法,减少耦合.
只需要在不同的时间应用不同的业务规则,就可以考虑使用策略模式进行处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
public abstract class CashSuper { public abstract double acceptCash(double price, int num); }
public class CashNormal extends CashSuper{ public double acceptCash(double price, int num) { return price * num; } }
public class CashRebate extends CashSuper { private double moneyRebate = 1d; public CashRebate(double moneyRebate){ this.moneyRebate = moneyRebate; }
public double acceptCash(double price, int num){ return price * num * moneyRebate; } }
public class CashReturn extends CashSuper { private double moneyCondition = 0d; private double moneyReturn = 0d;
public CashReturn(double moneyCondition, double moneyReturn){ this.moneyCondition = moneyCondition; this.moneyReturn = moneyReturn; }
public double acceptCash(double price, int num){ double ans = price * num; if (moneyCondition > 0 && ans >= moneyCondition){ ans -= Math.floor(ans / moneyCondition) * moneyReturn; } return ans; } }
public class CashContext { private CashSuper cs; public CashContext(CashSuper cs){ this.cs = cs; }
public double getResult(double price, int num){ return cs.acceptCash(price, num); } }
public class Main { public static void main(String[] args) { System.out.println("输入策略: 1 - 正常收费; 2 - 打八折; 3 - 打七折; 4 - 满300减100"); Scanner in = new Scanner(System.in); int discount = in.nextInt(); System.out.println("输入产品的单价:"); double price = in.nextDouble(); System.out.println("输入产品的数量:"); int num = in.nextInt(); in.close(); CashContext cs = null; switch (discount) { case 1: cs = new CashContext(new CashNormal()); break; case 2: cs = new CashContext(new CashRebate(0.8d)); break; case 3: cs = new CashContext(new CashRebate(0.7d)); break; case 4: cs = new CashContext(new CashReturn(300d, 100d)); break; default: System.out.println("we dont support this strategy"); break; } double totalPrice = cs.getResult(price, num); System.out.println(totalPrice); } }
|
- 策略模式,使用
CashContext
计算不同策略下的收费及结果,但是会发现在Main
中进行了判断需要使用哪一个策略
- 可以使用工厂模式+策略模式的方法进行调整
策略 + 工厂模式
只需要将Main
中的switch
部分移动到CashContext
中即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| public class CashContext { private CashSuper cs;
public CashContext(int discount){ switch (discount) { case 1: cs = new CashNormal(); break; case 2: cs = new CashRebate(0.8d); break; case 3: cs = new CashRebate(0.7d); break; case 4: cs = new CashReturn(300d, 100d); break; default: System.out.println("we dont support this strategy"); break; } }
public double getResult(double price, int num){ return cs.acceptCash(price, num); } }
|
在导航中,不同的路径规划算法,比如步行,骑行,搭乘公共交通的,开车的.主要导航类的主要工作是渲染路径,不会在意算法生成的路径,因此可以将路径规划算法使用策略模式进行封装,方便交互

- 策略模式不适合算法极少变化的场景,这样会使得程序整体变得复杂
- 同时要求客户知晓策略的不同