策略模式(java)

本文通过一个简单的商场收银系统的案例,详细介绍了策略模式与简单工厂模式的结合使用方法,包括如何定义计费功能的基类、实现具体计费策略的子类以及如何在Context类中统一调用这些策略。通过此示例,读者可以更好地理解这两种设计模式在实际编程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概念

策略模式(Strategy):它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法的变化不会影响到使用算法的客户。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)

图1 策略模式类图

 优点:

  1、 简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。
  2、 避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。
3、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

  缺点:
  1、 因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。
2、 在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。(这本身没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由Context来承担,这就最大化的减轻了客户端的压力。)

参考阅读:
1.<iframe name="dd_ads_frame" width="242" height="122" frameborder="0" src="http://union.dangdang.com/ads/unionads/?client=P-265530&amp;ad_client=P-265530&amp;ad_format=20&amp;product_id=9113943&amp;display_style=1&amp;open_target=_blank&amp;border=1&amp;ad_width=242&amp;ad_height=122&amp;url=http%3A%2F%2Fwww.cnblogs.com%2Fcolinsong%2Farchive%2F2009%2F03%2F02%2F1401723.html&amp;u_h=768&amp;u_w=1366&amp;u_ah=728&amp;u_aw=1366&amp;u_cd=32&amp;u_tz=480&amp;u_his=1&amp;u_java=true&amp;u_nplug=31&amp;u_nmime=58" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" style="margin: 0px; padding: 0px;"></iframe>2.<iframe name="dd_ads_frame" width="242" height="122" frameborder="0" src="http://union.dangdang.com/ads/unionads/?client=P-265530&amp;ad_client=P-265530&amp;ad_format=20&amp;product_id=20079096&amp;display_style=1&amp;open_target=_blank&amp;border=1&amp;ad_width=242&amp;ad_height=122&amp;url=http%3A%2F%2Fwww.cnblogs.com%2Fcolinsong%2Farchive%2F2009%2F03%2F02%2F1401723.html&amp;u_h=768&amp;u_w=1366&amp;u_ah=728&amp;u_aw=1366&amp;u_cd=32&amp;u_tz=480&amp;u_his=1&amp;u_java=true&amp;u_nplug=31&amp;u_nmime=58" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" style="margin: 0px; padding: 0px;"></iframe>

二、我的理解

其实这个策略模式和简单工厂模式一样,仅仅是对面向对象继承中常用的Override技术的一种应用。简单工厂模式中有一个工厂类,负责根据输入参数的不同来生成不同的子类,并将生成的子类作为基类返回(这样可以让客户端在使用的时候很方便)。客户端只需要调用工厂类创建一个基类的实例,然后调用这个实例的函数来实现自己的功能。而策略模式中的Context类的功能基本上就是对工厂类的强化版本,它也负责根据输入参数来生成不同的类,只是它并不返回生成类,而是将生成类所实现的功能接口包装一次,提供给客户。这样对客户来说,他们只需要知道这一个Context类就可以完成他们想要的功能,而不必再知道其他的信息。

三、策略模式与简单工厂模式结合的代码实现

下面以一个简单的商场收银系统为例,演示一下策略模式与简单工厂模式结合的使用。我将这个系统用两个工程实现。一个工程实现商场计费的业务功能,另一个工程用于实现POS机上的界面,也就是客户端。

首先介绍第一个工程:

1. 实现计费功能的基类(这里用抽象类实现):


1namespaceColinSong.DesignPattern.Strategy
2{
3publicabstractclassBillingAlgorithm
4{
5publicabstractdoublegetBillingResult(doubleprice,intquantity);
6}
7}

2. 实现具体计费功能的子类:

2.1 实现打折计费的子类:


1namespaceColinSong.DesignPattern.Strategy
2{
3publicclassBillingStrategy_Rebate:BillingAlgorithm
4{
5doublediscounts;
6publicBillingStrategy_Rebate(doublediscounts)
7{
8if(discounts<0.0000001||discounts>=1)
9{
10this.discounts=1;
11}
12else
13{
14this.discounts=discounts;
15}
16}
17
18publicoverridedoublegetBillingResult(doubleprice,intquantity)
19{
20returnprice*quantity*discounts;
21}
22}
23}

2.2 实现返现计费功能的子类:


1namespaceColinSong.DesignPattern.Strategy
2{
3publicclassBillingStrategy_CashReturn:BillingAlgorithm
4{
5intCashCondition;
6intCashReturn;
7publicBillingStrategy_CashReturn(intCashCondition,intCashReturn)
8{
9if(CashCondition<=0)
10{
11CashCondition=1;
12}
13if(CashReturn<=0)
14{
15CashReturn=1;
16}
17this.CashCondition=CashCondition;
18this.CashReturn=CashReturn;
19}
20
21publicoverridedoublegetBillingResult(doubleprice,intquantity)
22{
23doubleorignal=price*quantity;
24intn=(int)(orignal/CashCondition);
25returnorignal-CashReturn*n;
26}
27}
28}
29

3. Context类


1namespaceColinSong.DesignPattern.Strategy
2{
3publicclassBilling
4{
5//维护一个算法基类的实例
6BillingAlgorithmbillingAlgorithm;
7
8//简单工厂模式的构造函数
9publicBilling(stringBillingStrategy)
10{
11switch(BillingStrategy)
12{
13case"打8折":
14billingAlgorithm=newBillingStrategy_Rebate(0.8);
15break;
16case"满200返40":
17billingAlgorithm=newBillingStrategy_CashReturn(200,40);
18break;
19default:
20billingAlgorithm=newBillingStrategy_Rebate(1);
21break;
22}

23}

24//策略模式的构造函数
25publicBilling(BillingAlgorithmbillingAlgorithm)
26{
27this.billingAlgorithm=billingAlgorithm;
28}

29//这是策略模式的典型特征
30publicdoubleGetResult(doubleprice,intquantity)
31{
32returnbillingAlgorithm.getBillingResult(price,quantity);
33}

34}

35}

36

好,算法完成了,下面介绍客户端,界面如图2所示:

图2. 商场收银系统界面

下面看一下,确定按钮后面的代码:


privatevoidbtnOK_Click(objectsender,EventArgse)
{
\\只需要知道这个Context类,实例化它;
Billingbilling=newBilling(cbxBillingType.Text);
\\并调用它提供的方法,即可完成我们需要的功能。
doublecharge=billing.GetResult(double.Parse(txtPrice.Text),
int.Parse(txtQuantity.Text));
totalCash=totalCash+charge;
stringitemShow="单价:"+txtPrice.Text
+"\t数量:"+txtQuantity.Text+
".\t实收:"+charge.ToString()
+"\t"+cbxBillingType.Text;
list.Items.Add(itemShow);
lblSum.Text=totalCash.ToString();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值