行为型之设计模式-策略模式

行为型之设计模式

  • 简述
    • 一、策略模式
      • 一个简单的使用场景
        • 分析场景,抽离出关键点的简图
        • 实操demo
      • 策略模式小结

简述

设计模式类型有3种(行为型,创建型,结构型),以下逐一列出行为型类型的设计模式:
模板方法,命令模式,访问者模式,迭代器模式,观察者模式,中介者,备忘录,解释器,状态,策略,职责连模式(责任链模式)

一、策略模式

封装多种计算方式的算法包。即:
多个算法封装成一个算法包,一个接口的不同实现,对其方法做重写。优点:最主要是解决ifelse的问题。缺点:会导致类变很多

一个简单的使用场景

需求场景:
电影院为不同类型用户提供不同电影票的打折方式,方案:
1 学生凭学生证享受8折优惠
2 年龄在1-周岁及以下儿童可享受每张电影票减免10元优惠(原始票价不能低于20)
3 vip 用户可享受5折优惠,与此同时额外获取积分,可用积分兑换影院赠品
后期可能还会有优惠折扣方案。

分析场景,抽离出关键点的简图

1 涉及到折扣方案的封装
2 针对不同角色的切换
3 后期要考虑的复用。
确认过眼神,正对策略模式。

4此场景的开发简图:
上图

实操demo

 public class Client {public static void main(String[] args) {//业务中通过一些前置条件,判断走孩子/vip/学生  折扣类BigDecimal originPrice=new BigDecimal("79.99");new MovieTicket(originPrice,new ChildrenDiscount()).getPrice();;originPrice=new BigDecimal("88");new MovieTicket(originPrice,new VIPDiscount()).getPrice();}
}
/**环境策略角色*/
public class MovieTicket {BigDecimal price;Discount discount;public MovieTicket(BigDecimal price,Discount discount) {this.price=price;this.discount=discount;System.out.println("原始票价为:"+price.toString());}public BigDecimal getPrice() {return discount.calculate(this.price);}public void setPrice(BigDecimal originPrice) {this.price = originPrice;}public void setDiscount(Discount discount) {this.discount=discount;}
}
/**抽象策略角色*/
public interface Discount {BigDecimal calculate(BigDecimal originPrice);
}
/**具体策略角色*/
public class StudentDiscount implements Discount {private final BigDecimal DISCOUNT=new BigDecimal("0.8");@Overridepublic BigDecimal calculate(BigDecimal originPrice) {BigDecimal price= originPrice.multiply(DISCOUNT).setScale(2,BigDecimal.ROUND_HALF_UP);System.out.println("学生票价:"+price.toString());return price;}
}
/**具体策略角色*/
public class ChildrenDiscount implements Discount{private final BigDecimal DISCOUNT=new BigDecimal(10);@Overridepublic BigDecimal calculate(BigDecimal originPrice) {BigDecimal price=originPrice.compareTo(new BigDecimal(20))>=0?originPrice.subtract(DISCOUNT):originPrice;System.out.println("原票价至少20元,少儿票价方可优惠:"+price.toString());return price;}
}
/**具体策略角色*/
public class VIPDiscount implements  Discount {private final BigDecimal DISCOUNT=new BigDecimal("0.5");@Overridepublic BigDecimal calculate(BigDecimal originPrice) {BigDecimal price= originPrice.multiply(DISCOUNT);System.out.println("VIP票价:"+price.toString()+"可积分");return price;}
}

以上为策略模式小demo,看到这就可以直接看小结了。
代码上传到csdn了,可以下载测试。

策略模式小结

工作中使用率蛮高的。
同类场景,eg1: 借贷平台的还款方式,可用策略模式去计算不同还款方式的还款计划:一次性还本付息,先息后本,等额本金,等额本息,弹性还款,这些算法包均可作为具体策略角色进行封装。
eg2:接存管平台接口开发时,比如预处理,调用接口 以及后处理,可以采取策略模式。

优点小结:
1 对某一业务数据操作行为有多个算法包,客户针对自己需求调用其中的一个算法。
2 可灵活切换,可复用,封装多个算法包,完美满足设计模式开闭原则,可扩展性强。

据说的劣势,客户端要知道每种算法的用户,然后对自己的需求去调用,但如果算法方案是从客户端需求发起呢,哈哈,工作中一般都是业务方发起需求,驱动科技落地,如果是这种,那么该缺点可以忽略。

以上小结仅供参考,并不全面,仅个人看中的层面的总结,如有差错,请不吝指教~

附注:

如果你还想要使用xml形式,可参看下面追加code。将具体策略模式配置到xml文件中,每次新加策略后,在xml文件中改一下重启一下服务即可,实现方式如下:

/** 1 Client2.class 将具体策略角色类配置到xml中,通过xml解析工具类获取该具体策略角色类的实例走后续流程*/
public class Client2 {public static void main(String[] args) {BigDecimal originalPrice=new BigDecimal(60.0);Discount disount=(Discount) XMLUtil.getBean();;//读取配置文件并反射生成具体折扣对象MovieTicket mt=new MovieTicket(originalPrice,disount);mt.getPrice();}
}
2 添加xml文件解析工具包import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.IOException;public class XMLUtil {//该方法用于从xml配置文件中提取具体类的类名,并返回一个实例对象public static Object getBean(){try {DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();DocumentBuilder builder=dFactory.newDocumentBuilder();Document doc;doc=builder.parse(new File("src//strategyBook//config.xml"));//获取包含类型的文本节点NodeList nl=doc.getElementsByTagName("className");Node classNode=nl.item(0).getFirstChild();String cName=classNode.getNodeValue();//通过类名生成实例对象并将其返回Class c=Class.forName(cName);Object obj=c.newInstance();return obj;} catch (Exception e) {e.printStackTrace();return null;}}
}
3config.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<config><className>strategyBook.VIPDiscount</className>
</config>

xml配置具体策略角色:
优点:每次新增可添加具体策略角色类,同步修改xml文件后重启即可。清晰明了
缺点,不够灵活,试想,面对的前置条件是不同角色,要走各自对应的具体策略角色,那岂不是每走完一次数据 都要修改配置文件,然后重启服务?

参阅:
[1]: java设计模式,刘伟 编著


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部