案例
做一个商场的收银软件,根据客户的所购买的商品的单价和数量去收费
代码
主实现
package day2;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
Product product1=new Product("苹果",5,3);
Product product2=new Product("香蕉",6,5);
List<Product> products=new ArrayList<>();
products.add(product1);
products.add(product2);
PointSale pos=new PointSale();
double total=pos.calculateTotal(products);
System.out.println(total);
}
}
商品类
package day2;
public class Product {
String name;
double price;
int quantity;
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", price=" + price +
", quantity=" + quantity +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public Product(String name, double price, int quantity) {
this.name = name;
this.price = price;
this.quantity = quantity;
}
}
收银机类
package day2;
import java.util.List;
public class PointSale {
public double calculateTotal(List<Product> products){
double total=0;
for(Product product:products){
total+=product.getPrice()*product.getQuantity();
}
return total;
}
}
问题1
如果要增加打折的代码怎么办或者是需要满减的活动代码 我们需要去思考一下 有什么东西是相同的
简单工厂类的处理方法
工厂类
package day2;
public class cashFactory {
public static cashSuper creatCashAccept(String type){
cashSuper cs=null;
switch (type){
case"正常收费":
cs=new CashNormal();
break;
case"满300反10":
CashReturn cr1=new CashReturn(300,10);
cs=cr1;
break;
case"打折":
cashRebate cr2=new cashRebate(0.8);
cs=cr2;
break;
}
return cs;
}
}
正常收费类
package day2;
public class CashNormal extends cashSuper {
@Override
public double acceptCash(double money) {
return money;
}
}
返利类
package day2;
public class cashRebate extends cashSuper{
public cashRebate(double rebate) {
this.rebate = rebate;
}
double rebate=0;
@Override
public double acceptCash(double money) {
return rebate*money;
}
}
买多少反多少类
package day2;
public class CashReturn extends cashSuper{
double moneyCondition=0;
double moneyReturn=0;
public CashReturn(double moneyCondition, double moneyReturn) {
this.moneyCondition = moneyCondition;
this.moneyReturn = moneyReturn;
}
@Override
public double acceptCash(double money) {
double result=0;
if (money>=moneyCondition)
result=money-Math.floor(money/moneyCondition)*moneyReturn;
return result;
}
}
抽象收费类
package day2;
abstract class cashSuper {
public abstract double acceptCash(double money);
}
客户端代码
缺点:
简单工厂模式虽然可以解决这个问题,但这个模式只是解决对象的创建问题,而且由于工厂本身包括了所有的收费方式,商场是可能经常性的更改打折额度和返利额度,每次维护的话都要去改动这个工厂,以至于代码需要去重新编译部署。
策略模式:
定义:
定义一系列算法,封装每一个算法,并使他们可以互换。
像商场收银时如何促销,用打折还是返利,其实都是一些算法,用工厂来生成算法对象。
策略模式在实际的开发中很常见,最常见的应用场景是利用他来替换过多的if-else嵌套的逻辑判断。
代码
context
package day2;
public class CashContext {
private cashSuper cs;
public CashContext(cashSuper cs) {
this.cs = cs;
}
public double GetResult(double money){
return cs.acceptCash(money);
}
}
客户端代码也需要去修改一下
缺点:
代码回到了原来的老路 需要去用客户端去判断使用哪一个算法 那怎么就可以将这个判断的过程从客户端程序中转移走呢 ------------原来的简单工厂就可以完成这个任务 ----------------简单工厂不一定非要是一个单独的类 可以和策略模式的context去结合
策略和简单模式结合
代码
context
package day2;
public class CashContext {
cashSuper cs=null;
public CashContext(String type){
switch (type){
case"正常收费":
cs=new CashNormal();
break;
case"满300反10":
CashReturn cr1=new CashReturn(300,10);
cs=cr1;
break;
case"打折":
cashRebate cr2=new cashRebate(0.8);
cs=cr2;
break;
}
}
public CashContext(cashSuper cs) {
this.cs = cs;
}
public double GetResult(double money){
return cs.acceptCash(money);
}
}
客户端
就是将cashFactory中的代码搬过来 客户端代码稍作改变 剩下的一样
客户端代码的不同之处
策略模式 解析
策略模式是一种定义一系列算法的方法,从概念上来看 所有的这些算法完成的都是相同的工作 知识实现不同 它可以用相同的方式去调用所有的算法 减少了各种算法类与只用算法类之间的耦合
策略模式的strategy类层次为context定义了一系列可以重用的算法或行为 继承有助于吸取出这些算法中的公共功能
策略模式简化了单元测试 因为每一个算法都有自己的类 可以通过自己的接口单独测试