本篇文章的场景是模拟一个商场收银软件,营业员根据客户所购买商品的单价和数量向客户收费。使用简单工厂模式和策略模式分别进行实现。
简单工厂模式实现:
使用类对收费进行抽象:面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象集合才是类。
现金收费类:
package chapter2.factory;
public abstract class CashSuper {
/**
* This method is used to calculate the money should be charged.
* @param money money to be charged
* @return
*/
public abstract double acceptCash(double money);
}
package chapter2.factory;
public class CashNormal extends CashSuper {
@Override
public double acceptCash(double money) {
return money;
}
}
package chapter2.factory;
public class CashRebate extends CashSuper {
/* Rebate ratio*/
private double moneyRebate = 1d;
public CashRebate(String moneyRebate) {
this.moneyRebate = Double.parseDouble(moneyRebate);
}
@Override
public double acceptCash(double money) {
return money * this.moneyRebate;
}
}
package chapter2.factory;
public class CashReturn extends CashSuper {
/* Condition should return money */
private double moneyCondition = 0.0d;
/* Money should be returned */
private double moneyReturn = 0.0d;
public CashReturn(String moneyCondition, String moneyReturn) {
this.moneyCondition = Double.parseDouble(moneyCondition);
this.moneyReturn = Double.parseDouble(moneyReturn);
}
@Override
public double acceptCash(double money) {
double result = money;
if(money >= moneyCondition) {
result = money - Math.floor(money / moneyCondition) * moneyReturn;
}
return result;
}
}
模拟收费系统
package chapter2.factory;
/**
* @author CHK
* 简化收费系统
*/
public class CashSystem {
public static void main(String[] args) {
double total = 0d;
double txtPrice = 10;
double txtNum = 10;
String policy = "80% rebate";
CashSuper csuper = CashFactory.createCashAccept(policy);
double totalPrice = csuper.acceptCash(txtPrice * txtNum);
total += totalPrice;
System.out.println("单价:" + txtPrice +"\n数量:" + txtNum + "\n策略:" + policy +
"\n合计:" + total);
}
}
策略模式:定义了算法家族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
策略模式代码如下:
package chapter2.policy;
import chapter2.factory.CashSuper;
/**
* @author CHK
* 收费策略类
*/
public class CashContext {
private CashSuper cs;
public CashContext(CashSuper csuper) {
this.cs = csuper;
}
public double getResult(double money) {
return cs.acceptCash(money);
}
}
package chapter2.policy;
import chapter2.factory.CashNormal;
import chapter2.factory.CashRebate;
import chapter2.factory.CashReturn;
/**
* @author CHK
* 简化收费系统
*/
public class CashSystem {
public static void main(String[] args) {
CashContext cc = null;
double total = 0d;
double txtPrice = 10;
double txtNum = 10;
String policy = "80% rebate";
switch(policy) {
case "Normal":
cc = new CashContext(new CashNormal());
break;
case "Return 100 when greater than 300":
cc = new CashContext(new CashReturn("300", "100"));
break;
case "80% rebate":
cc = new CashContext(new CashRebate("0.8"));
break;
}
double totalPrice = cc.getResult(txtPrice * txtNum);
total += totalPrice;
System.out.println("单价:" + txtPrice +"\n数量:" + txtNum + "\n策略:" + policy +
"\n合计:" + total);
}
}
简单工厂模式下需要让收费系统认识两个类CashSuper和CashFactory,而策略模式和简单工厂模式相结合的话就可以只让收费系统关注CashContext这一个类,从而减小耦合性。代码如下:
package chapter2.policyfactory;
import chapter2.factory.CashSuper;
import chapter2.factory.CashNormal;
import chapter2.factory.CashRebate;
import chapter2.factory.CashReturn;
public class CashContext {
private CashSuper cs;
public CashContext(String type) {
switch(type) {
case "Normal":
cs = new CashNormal();
break;
case "Return 100 when greater than 300":
cs = new CashReturn("300", "100");
break;
case "80% rebate":
cs = new CashRebate("0.8");
break;
}
}
public double getResult(double money) {
return cs.acceptCash(money);
}
}
package chapter2.policyfactory;
/**
* @author CHK
* 简化收费系统
*/
public class CashSystem {
public static void main(String[] args) {
double total = 0d;
double txtPrice = 100;
double txtNum = 10;
String policy = "Return 100 when greater than 300";
CashContext cc = new CashContext(policy);
double totalPrice = cc.getResult(txtPrice * txtNum);
total += totalPrice;
System.out.println("单价:" + txtPrice +"\n数量:" + txtNum + "\n策略:" + policy +
"\n合计:" + total);
}
}
策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合,策略模式的Strategy类蹭吃为Context定义了一系列可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。策略模式的优点是简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。