简单工厂模式

需要实例化谁,以后可能会添加实例化的对象,就要用一个单独的类来做这个创造实例的过程,就是工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Operation.java
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;
}
}

问题:

  1. 如果需要增加函数,就需要添加新的case,有可能会改变原有的函数;
  2. 如果代码只需要调用除法,却需要编译其他的加,减,乘函数
    解决办法:
    实现一个运算抽象类,都有一个方法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
// Operation.java
public abstract class Operation {
public double getResult(double numberA, double numberB){
return 0d;
}
}

// Add.java
public class Add extends Operation{
public double getResult(double numberA, double numberB){
return numberA + numberB;
}
}

// Sub.java
public class Sub extends Operation{
public double getResult(double numberA, double numberB){
return numberA - numberB;
}
}

// Mul.java
public class Mul extends Operation{
public double getResult(double numberA, double numberB){
return numberA * numberB;
}
}

// Div.java
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;
}
}

// OperationFactory.java
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;
}
}

// Main.java
Operation oper = OperationFactory.createOperation(flag);
double ans = oper.getResult(a, b);

SFP

三个角色:

  1. 抽象类: 定义所有支持算法的公共接口,比如运算抽象类
  2. 具体算法类: 具体的算法,比如加减乘除运算类
  3. 简单工厂类: 用来维护对运算类的应用
  • 可以将类类比为产品,使用者在不清楚类生产的具体过程的情况下,可以使用不同的产品.

策略模式

定义算法家族,分别封装,让他们之间可以相互替换.这样可以保证算法的变化不会影响到客户
一系列算法都完成相同的工作,只是实现不同,可以以相同的方式调用所有的算法,减少耦合.
只需要在不同的时间应用不同的业务规则,就可以考虑使用策略模式进行处理

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
// CashSuper.java
// 收费抽象类
public abstract class CashSuper {
// 收费的抽象方法,参数为单价和数量
public abstract double acceptCash(double price, int num);
}

// CashNormal.java
public class CashNormal extends CashSuper{
public double acceptCash(double price, int num) {
return price * num;
}
}

// CashRebate.java
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;
}
}

// CashReturn.java
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;
}
}

// CashContext.java
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);
}
}

// Main.java
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
// CashContext.java
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);
}
}

在导航中,不同的路径规划算法,比如步行,骑行,搭乘公共交通的,开车的.主要导航类的主要工作是渲染路径,不会在意算法生成的路径,因此可以将路径规划算法使用策略模式进行封装,方便交互

SP

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