大话设计模式-Java实现(2)-策略模式

面向对象的编程,并不是类越多越好,类的划分是为了封装,但分类的基础是抽象,具有相同属性和功能的对象的抽象几何才是类。

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、由于策略模式把每个具体的策略实现都单独封装成为类,如果备选的策略很多的话,那么这些类的数目就非常多了。

发布了53 篇原创文章 · 获赞 33 · 访问量 1267

猜你喜欢

转载自blog.csdn.net/qq_44458489/article/details/104870984
今日推荐