释义
工厂模式,那就和工厂有些许关系,工厂是用来干什么的,生产产品的,那在设计模式中,工厂模式也正如字面含义一样,可以生产一些东西。在java中,工厂模式一般都是用来实例化对象模式了,是用工厂方法代替new操作的一种模式。
案例
编写一个超市打折促销的计算方式,有三种计算方式,原价、打折、满减。我们根据该需求设计一个程序,如下。
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int s = Integer.parseInt(scanner.nextLine());
double price = 200;
int num = 2;
double result = 0;
//1:原价,2:打8折,3:满300减去100
switch (s) {
case 1:
result = price * num;
break;
case 2:
result = price * num * 0.8;
break;
case 3:
double total = price * num;
if (total >= 300) {
total -= Math.floor(total / 300) * 100;
}
result = total;
break;
}
System.out.println("最终售价为:" + result);
}
如代码所示,三种情况我们写一个switch对不同情况做不同计算即可,这样看着好像也没什么问题,但是如果后面再加几种计算方式,我们就需要在继续拼接switch了。这样一旦活动有所更改,或者增加,都需要修改这个类,所有的业务,计算都在一个类中。这样实在不是很符合开发的设计理念。
我们应该把计算放到后面,在mvc模式的开发下,计算应该是service做的事情。而switch的选择,是视图所需要做的工作。而且最好是把所有的促销模式一一做一次封装,这样以后如果对一种活动做修改,那么就不会改动其他的活动。代码做如下改动
public class CashNormal{
public double acceptCash(double price, int num) {
return price * num;
}
}
public class CashRebate{
//折扣值
private double zk;
public CashRebate(double zk) {
this.zk = zk;
}
public double acceptCash(double price, int num) {
return price * num * zk;
}
}
public class CashReturn{
//满减需要达到额度
private double m;
//减去数值
private double j;
public CashReturn(double m, double j) {
this.m = m;
this.j = j;
}
public double acceptCash(double price, int num) {
double total = price * num;
if (total >= m) {
total -= Math.floor(total / m) * j;
}
return total;
}
}
double result = 0;
switch (s){
case 1:
CashNormal c1 = new CashNormal();
result = c1.acceptCash();
break;
case 2:
CashRebate c2 = new CashRebate(0.8);
result = c2.acceptCash();
break;
case 3:
CashRebate c3 = new CashRebate(300, 100);
result = c3.acceptCash();
break;
}
System.out.println("最终售价为:" + result);
经过如上操作,把计算业务单独封装类,后续对其中一种算法做修改就可以减少对其他算法的影响。但是对于业务来说,不管是原价,还是打折,都是属于一种销售计价方式,这时候我们可以用继承父类的方式,使用多态的特性做个修改。创建CashSuper类,CashNormal、CashRebate、CashReturn类都继承该父类。再将switch做修改。
public abstract class CashSuper {
public abstract double acceptCash(double price, int num);
}
CashSuper cs = null;
switch (s){
case 1:
cs = new CashNormal();
break;
case 2:
cs = new CashRebate(0.8);
break;
case 3:
cs = new CashReturn(300, 100);
break;
}
System.out.println("最终售价为:" + cs.acceptCash());
这里就可以使用工厂模式特性再做一次封装,switch中根据不同情况产生三个对象,其实正是工作需要做的事情,我们把这一段逻辑单独放一个CashFactory的类中。
public class CashFactory {
public static CashSuper getSf(int s){
CashSuper cs = null;
switch (s){
case 1:
cs = new CashNormal();
break;
case 2:
cs = new CashRebate(0.8);
break;
case 3:
cs = new CashReturn(300, 100);
break;
}
return cs;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int s = Integer.parseInt(scanner.nextLine());
CashSuper cs = CashFactory.getSf(s);
double result = cs.acceptCash(200, 2);
System.out.println(result);
}
简单工厂模式在设计模式中算比较容易理解的模式,这里直接写出例子就可以看出该模式在这个需求中起到的作用。客户端不再进行判断,也不再关注计算公式。只需要知道需要的促销方式,传送给工厂,工厂根据类型去生产出一个对应的计算对象。再通过多态使用父类对象进行调用子类的具体实现方法。