策略模式

 

概述:

      策略模式就是定义了一个对象在不同场景下的不同操作。比如:发票这个对象,会根据不同的类型对应不同的统计方式。

使用场景:

      但凡有3个以上的if 出现的地方,都可以考虑使用策略模式来代替,当然要依据具体的业务场景,比如应用程序对数据库的操作,就四种(select insert update delete)像这样的场景我们没有必要为了用策略而用。 我们用设计模式的初衷是增强程序的健壮性、稳定性、扩展性。下面我们通过一个简单的案例具体说明。

组成:

      抽象策略:通常是一个接口或者一个类

      具体策略:集成抽象策略或者实现策略接口

      环境角色:持有一个抽象策略的引用

实战:

      业务场景:税务系统中,需要对不同类型的发票根据不同的规则做统计,然后按照不同的税率计算税款。

      方案一:通过if else或者 switch 相信大家都会

/**
 * @date 2020年9月4日17:50:37
 * @author liujl
 */
public class InvoiceCount {
	
	private static final List<String> INVOICE_TYPE = Arrays.asList("ZZS", "TXS", "HGS");
	
	private static Object countByIf(List<?> invoices, String invoiceType) {
		if (!INVOICE_TYPE.contains(invoiceType)) {
			return null;
		} 
		if (Objects.equals(INVOICE_TYPE.get(0), invoiceType)) {
			System.out.println("按照增值税规则统计发票");
		}
		if (Objects.equals(INVOICE_TYPE.get(1), invoiceType)) {
			System.out.println("按照通行税规则统计发票");
		}
		if (Objects.equals(INVOICE_TYPE.get(2), invoiceType)) {
			System.out.println("按照海关税规则统计发票");
		}
		return null;
	}
	
	private static Object countBySwitch(List<?> invoices, String invoiceType) {
		switch (invoiceType) {
		case "ZZS":
			System.out.println("按照增值税规则统计发票");
			break;
		case "TXS":
			System.out.println("按照通行税规则统计发票");
			break;
		case "HGS":
			System.out.println("按照海关税规则统计发票");
			break;
		default:
			break;
		}
		return null;
	}
	
	public static void main(String[] args) {
		List<?> invoices = new ArrayList<>();
		for (String object : INVOICE_TYPE) {
			countByIf(invoices, object);
		}
		for (String object : INVOICE_TYPE) {
			countBySwitch(invoices, object);
		}
	}

}

      方案二:使用策略模式,以下代码:

// 抽象策略
public interface InvoiceStrategy {
	
	default Object count(List<?> invoices) {
		// 通用的统计规则
		System.out.println("通过通用的规则统计发票");
		return null;
	}
}

 下面是三个具体策略:

// 增值税策略
public class ZzsInvoice implements InvoiceStrategy {

	@Override
	public Object count(List<?> invoices) {
		System.out.println("按照增值税发票的规则进行统计");
		return null;
	}

}
// 海关税策略
public class HgsInvoice implements InvoiceStrategy {

	@Override
	public Object count(List<?> invoices) {
		System.out.println("按照海关税发票的规则进行统计");
		return null;
	}

}
​
// 通行税,使用默认策略
public class TxsInvoice implements InvoiceStrategy {}

​

 

/**
 * 环境角色
 */
public class InvoiceContext {
	
	private InvoiceStrategy invoiceStrategy;
	
	private List<?> invoices;

	public InvoiceContext(InvoiceStrategy invoiceStrategy, List<?> invoices) {
		this.invoiceStrategy = invoiceStrategy;
		this.invoices = invoices;
	}
	
	public Object count() {
		return this.invoiceStrategy.count(invoices);
	}
	
	/**
	 * 触发点
	 * @param args
	 */
	public static void main(String[] args) {
		InvoiceContext zzs = new InvoiceContext(new ZzsInvoice(), new ArrayList<Object>());
		zzs.count(); // 按照增值税发票的规则进行统计
		InvoiceContext hgs = new InvoiceContext(new HgsInvoice(), new ArrayList<Object>());
		hgs.count(); // 按照海关税发票的规则进行统计
		InvoiceContext txs = new InvoiceContext(new TxsInvoice(), new ArrayList<Object>());
		txs.count(); // 通过通用的规则统计发票
	}

}

优缺点比对:

 方案一方案二
文件数量1n(具体策略的数量)+2
可读性
可维护性
扩展性

       解读:当具体策略很少(小于5)且每个策略的代码量不大(小于30行)同时业务逻辑简单的时候,其实两种方案的区别看上去似乎不大。但是当其中一种策略的代码量达到数百行的时候,你会发现一个if条件里面会有很多的if else for switch。。。这时修改一种策略的代码相应的维护成本、测试成本、开发成本都是很高的,这事其一其二:如果领导说我们又加了三种发票,如果我们采用方案一,只能再写第三个if或者三个case,而且在实际工作当中这三个if十有八九不是一个人写,这个时候还有代码冲突的成本, 而方案二只需要新建一个类继承或实现抽象策略即可;其三:后期维护成本高,当领导给你这样一个需求,你打开这个类一看,上万行代码,相信经历过的小伙伴们一定不会忘记当时的感受。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值