面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象几何才是类。
v1.0 商场收银软件
import java.util.Scanner;
//商场收银软件
//营业员根据客户所购买商品的单价和数量进行收费
public class Program1 {
public static void main(String[] args) {
//声明一个double变量total来计算总计
double total = 0.0;
String answer;
do {
System.out.println("请输入商品单价:");
String txtPrice = new Scanner(System.in).nextLine();
System.out.println("请输入商品数量:");
String txtNum = new Scanner(System.in).nextLine();
//声明一个double变量totalPrices来计算每个商品的单价(txtPrice)*数量(txtNum)后的合计
double totalPrices = Double.parseDouble(txtPrice) * Double.parseDouble(txtNum);
//将每个商品合计计入总计
total = total + totalPrices;
System.out.println("单价:" + txtPrice + " 数量:" + txtNum + " 合计:" + totalPrices);
System.out.println("是否继续输入商品? y继续 任意键退出");
answer = new Scanner(System.in).nextLine();
} while ("y".equals(answer));
System.out.println(total);
}
}
v2.0 增加打折
import java.util.Scanner;
//增加打折
public class Program2 {
public static void main(String[] args) {
//声明一个double变量total来计算总计
double total = 0.0d;
String answer;
do {
System.out.println("请输入商品单价:");
String txtPrice = new Scanner(System.in).nextLine();
System.out.println("请输入商品数量:");
String txtNum = new Scanner(System.in).nextLine();
System.out.println("请输入打折条件:0代表正常收费 1代表打八折 2代表打七折 3代表打五折");
String select = new Scanner(System.in).nextLine();
double totalPrices = 0d;
switch (select) {
case "0":
totalPrices = Double.parseDouble(txtPrice) * Double.parseDouble(txtNum);
break;
case "1":
totalPrices = Double.parseDouble(txtPrice) * Double.parseDouble(txtNum) * 0.8;
break;
case "2":
totalPrices = Double.parseDouble(txtPrice) * Double.parseDouble(txtNum) * 0.7;
break;
case "3":
totalPrices = Double.parseDouble(txtPrice) * Double.parseDouble(txtNum) * 0.5;
break;
}
total = total + totalPrices;
System.out.println("单价:" + txtPrice + " 数量:" + txtNum + " 合计:" + totalPrices);
System.out.println("是否继续输入商品? y继续 任意键退出");
answer = new Scanner(System.in).nextLine();
} while("y".equals(answer));
System.out.println(total);
}
}
v3.0 简单工厂实现
//正常收费子类
public class CashNormal extends CashSuper {
//正常收费,原价返回
@Override
public double acceptCash(double money) {
return money;
}
}
//打折收费子类
public class CashRebate extends CashSuper {
private double moneyRebate = 1;
//初始化时,必需要输入折扣率,如八折,就是0.8
public CashRebate(String moneyRebate) {
this.moneyRebate = Double.parseDouble(moneyRebate);
}
@Override
public double acceptCash(double money) {
return money * moneyRebate;
}
}
//返利收费子类
public class CashReturn extends CashSuper {
private double moneyCondition = 0.0d;
private double moneyReturn = 0.0d;
//初始化时必须要输入返利条件和返利值,比如满300返100,则moneyCondition为300,moneyReturn为100
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;
}
}
//现金收费工厂类
public class CashFactory {
//根据条件返回相应的对象
public static CashSuper createCashAccept(String type) {
CashSuper cs = null;
switch (type) {
case "0":
cs = new CashNormal();
break;
case "1":
CashReturn cr1 = new CashReturn("300", "100");
cs = cr1;
break;
case "2":
CashRebate cr2 = new CashRebate("0.8");
cs = cr2;
break;
}
return cs;
}
}
import java.util.Scanner;
//客户端代码
public class Program3 {
public static void main(String[] args) {
//声明一个double变量total来计算总计
double total = 0.0d;
String answer;
do {
System.out.println("请输入商品单价:");
String txtPrice = new Scanner(System.in).nextLine();
System.out.println("请输入商品数量:");
String txtNum = new Scanner(System.in).nextLine();
System.out.println("请输入打折条件:0代表正常收费 1代表满300减100 2代表打八折");
String select = new Scanner(System.in).nextLine();
//利用简单工厂模式根据输入的选项,生成相应的对象
CashSuper csuper = CashFactory.createCashAccept(select);
double totalPrices = 0d;
//通过多态,可以得到收取费用的结果
totalPrices = csuper.acceptCash(Double.parseDouble(txtPrice) * Double.parseDouble(txtNum));
total = total + totalPrices;
System.out.println("单价:" + txtPrice + " 数量:" + txtNum + " 合计:" + totalPrices);
System.out.println("是否继续输入商品? y继续 任意键退出");
answer = new Scanner(System.in).nextLine();
} while("y".equals(answer));
System.out.println(total);
}
}
v4.0 策略模式
CashSuper、CashNormal、CashRebate、CashReturn这几个类不用改,添加一个CashContext类。
//收费策略Context
public class CashContext1 {
//声明一个现金收费父类对象
private CashSuper cs;
//设置策略行为,参数为具体的现金收费子类(正常,打折或返利)
public CashContext(CashSuper csuper) {
this.cs = csuper;
}
//得到现金促销计算结果(利用了多态机制,不同的策略行为导致不同的结果)
public double GetResult(double money) {
return cs.acceptCash(money);
}
}
import java.util.Scanner;
//客户端代码
public class Program4 {
public static void main(String[] args) {
//声明一个double变量total来计算总计
double total = 0.0d;
String answer;
do {
System.out.println("请输入商品单价:");
String txtPrice = new Scanner(System.in).nextLine();
System.out.println("请输入商品数量:");
String txtNum = new Scanner(System.in).nextLine();
System.out.println("请输入打折条件:0代表正常收费 1代表满300减100 2代表打八折");
String select = new Scanner(System.in).nextLine();
//利用简单工厂模式根据输入的选项,生成相应的对象
CashSuper csuper = CashFactory.createCashAccept(select);
CashContext1 cc = new CashContext1(csuper);
switch (select) {
case "0":
cc = new CashContext1(new CashNormal());
break;
case "1":
cc = new CashContext1(new CashReturn("300", "100"));
break;
case "2":
cc = new CashContext1(new CashRebate("0.8"));
break;
}
double totalPrices = 0d;
totalPrices = cc.GetResult(Double.parseDouble(txtPrice) * Double.parseDouble(txtNum));
total = total + totalPrices;
System.out.println("单价:" + txtPrice + " 数量:" + txtNum + " 合计:" + totalPrices);
System.out.println("是否继续输入商品? y继续 任意键退出");
answer = new Scanner(System.in).nextLine();
} while("y".equals(answer));
System.out.println(total);
}
}
v5.0 策略与简单工厂结合
//收费策略Context
public class CashContext2 {
//声明一个现金收费父类对象
CashSuper cs = null;
//注意参数不是具体的收费策略对象,而是一个字符串,表示收费类型
//将实例化具体策略的过程由客户端转移到Context中。简单工厂的应用
public CashContext2(String type) {
switch (type) {
case "0":
cs = new CashNormal();
break;
case "1":
CashReturn cr1 = new CashReturn("300", "100");
cs = cr1;
break;
case "2":
CashRebate cr2 = new CashRebate("0.8");
cs = cr2;
break;
}
}
public double GetResult(double money) {
return cs.acceptCash(money);
}
}
import java.util.Scanner;
//客户端代码
public class Program5 {
public static void main(String[] args) {
//声明一个double变量total来计算总计
double total = 0.0d;
String answer;
do {
System.out.println("请输入商品单价:");
String txtPrice = new Scanner(System.in).nextLine();
System.out.println("请输入商品数量:");
String txtNum = new Scanner(System.in).nextLine();
System.out.println("请输入打折条件:0代表正常收费 1代表满300减100 2代表打八折");
String select = new Scanner(System.in).nextLine();
//利用策略模式和简单工厂模式结合根据输入的选项,生成相应的对象
CashContext2 cc = new CashContext2(select);
double totalPrices = 0d;
totalPrices = cc.GetResult(Double.parseDouble(txtPrice) * Double.parseDouble(txtNum));
total = total + totalPrices;
System.out.println("单价:" + txtPrice + " 数量:" + txtNum + " 合计:" + totalPrices);
System.out.println("是否继续输入商品? y继续 任意键退出");
answer = new Scanner(System.in).nextLine();
} while("y".equals(answer));
System.out.println(total);
}
}
Important:
简单工厂模式需要让客户端认识两个类 CashSuper、CushFactory 而策略模式与简单工厂结合的用法 客户端只需认识一个类CashContext就可以了 耦合更加降低。
策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以互相替换 此模式让算法的变化 不会影响到使用算法的客户。
策略模式是对多态的诠释,根据对象的不同,选择不同的算法进行实现。
在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。
优点:
简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单元测试。
缺点:
1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。这就意味着客户端必须理解这些算法的区别,以便适时选择恰当的算法类。换言之,策略模式只适用于客户端知道算法或行为的情况。
2、由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么这些类的数目就非常多了。