前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式学习之路一:策略模式

设计模式学习之路一:策略模式

作者头像
止术
发布2020-09-15 10:02:45
2670
发布2020-09-15 10:02:45
举报
文章被收录于专栏:求道求道

小弟最近在研究设计模式,准备边学边发博客,与众多大佬们交流学习,希望各位能够指出不足之处(废话不多说了,直接开花)

首先,最起码得知道为啥学习设计模式;不要被那些设计模式学了也用不上所误导,虽然设计模式的研究不是那么简单,现在所流行的设计模式也远不止23种,但是多学习设计模式,你会被那些编程大师们的编程思想所洗礼,要知道,编程并不是一个工作,而是一门哲学,面向对象编程体会颇深。在日常开发中,或许用或者不用设计模式,都能实现你的业务需求,但是,用设计模式会使你的代码日后更易于维护,(你说你代码写一次以后就不改了?牛逼,出门右拐,谢谢),往往用适当的设计模式,会使你在日后维护、升级代码上更加得心应手,能够很大几率避免牵一发而动全身的几率,(有过体会的很难受有木有,吼吼吼,改一个小功能,狠不得把整个工程重构),所以能够在日常开发中,学会常用一些符合你业务需求的设计模式,不往你是一个苦逼的程序猿,哈哈!

今天要说的设计模式使策略设计模式(Strategy)它定义了算法家族,分别封装起来,让算法与算法之间可以享胡替换,此模式的算法变化,不会影响到使用此算法的客户。


策略模式适用于什么场景呢?

主要解决的是你的系统里有很多相似的算法,你用if...else去维护很麻烦很复杂,比如说,商场逢年过节会推出打折活动; 此时让你去设计一个商场的商品购买后台,你需要实现 打八折 打五折 打一折 免费送(做梦) 满500返200........等等等各种算法,此时你就不得不去做各种判断,废话不多说,怼代码!

0.先看下策略模式的结构图

1.先写个商品类备用

package com.huangfu; /** * 商品类 * @author 皇甫 */ public class Product { private String name; private double price; @Override public String toString() { return "Product{" + "name='" + name + '\'' + ", price=" + price + '}'; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public Product() { } public Product(String name, double price) { this.name = name; this.price = price; } } 2. 定义收费接口 package com.huangfu; /** * 商场的收费接口类,应对商场的各种打折方式 * @author 皇甫 */ public interface Toll { /** * 商场的优惠方式 * @param money 原价 * @return 应付价格 */ public double offerMethod(double money); } 3.书写算法的实现类 实现商场的各种打折方式 package com.huangfu; /** * 商场正常收费 没有优惠 * @author 皇甫 */ public class NoDiscount implements Toll{ /** * * @param money 原价 * @return 返回商品原价 */ @Override public double offerMethod(double money) { return money; } } package com.huangfu; /** * 商场的额返利算法 入满300返100 * @author 皇甫 * */ public class RebateAlgorithm implements Toll { /** * 商场的返利力度 */ private double strength; private double scale; /** * @param strength 商场的返利力度 比如返100 * @param scale 商场的返利满足条件 比如满足300 */ public RebateAlgorithm(double strength, double scale) { this.strength = strength; this.scale = scale; } /** * @param money 原价 * @return 优惠后的价格 */ @Override public double offerMethod(double money) { double result = 0.0; if(money>=scale){ result = (strength/scale) * money; } return money - result; } } package com.huangfu; /** * 打折 * 商场打折的折扣算法 * @author 皇甫 */ public class DiscountAlgorithm implements Toll{ /** * 商场的折扣力度入打8折就是0.8 * */ private double strength; public DiscountAlgorithm(double strength) { this.strength = strength; } @Override public double offerMethod(double money) { return money*strength; } } 4.定义策略模式主体,管理各种算法 package com.huangfu; /** * 策略模式算法主体类 * @author 皇甫 */ public class Content { /** * 将算法关联到此主题类 我的理解是将各种算法交由主题类来管理 * */ private Toll t; /** * 指定算法实现 * @param t */ public Content(Toll t) { this.t = t; } /** * 返回优惠力度 * @param money * @return */ public double getResult(double money){ return t.offerMethod(money); } } 5.使用简单工厂管理策略主体类(你也可以不用,没人逼你;工厂模式后面会发表,持续关注喽!) package com.huangfu; /** * 商品计算的简单工厂 * @author 皇甫 */ public class CommodityFactory { /** * 默认正常收费 没有任何优惠力度 */ private static Content c = new Content(new NoDiscount()); /** * 设置优惠方式 * @param type 优惠方式 */ public static void setOffer(String type){ switch (type){ case "打八折": c = new Content(new DiscountAlgorithm(0.8)); case "满300返100": c = new Content(new RebateAlgorithm(100, 300)); } } /** * 返回最终的优惠价格 * @param money 应付价格 * @return 实付价格 */ public static double getResult(double money){ return c.getResult(money); } } 6.大功告成,测试走起,模拟购买商品 package com.huangfu; import java.util.HashMap; import java.util.Map; import java.util.Scanner; import java.util.Set; /** * 测试类 * @author 皇甫 */ public class TestMain { private static double price = 0.0; private static String type = "暂无优惠"; /** * 模拟购买 * @param args */ public static void main(String[] args) { type = "满300返100"; /** * 商场设置优惠方式 默认没有优惠 */ //CommodityFactory.setOffer(type); CommodityFactory.setOffer(type); Product p1 = new Product("超大冰淇淋", 100.0); Product p2 = new Product("风扇", 89.0); Product p3 = new Product("口香糖", 32.5); Product p4 = new Product("卫龙", 55.2); Product p5 = new Product("大面筋", 215.0); Product p6 = new Product("超大鱿鱼", 1000.5); Product p7 = new Product("八爪鱼酱", 55.5); Product p8 = new Product("小熊饼干", 66.6); Map<Integer,Product> product = new HashMap<Integer,Product>(); product.put(1, p1); product.put(2, p2); product.put(3, p3); product.put(4, p4); product.put(5, p5); product.put(6, p6); product.put(7, p7); product.put(8, p8); while (true){ Set<Map.Entry<Integer, Product>> entries = product.entrySet(); for (Map.Entry<Integer, Product> entry : entries) { System.out.println(entry.getKey()+":"+entry.getValue().getName()+" 价格"+entry.getValue().getPrice()); } System.out.println("-------------------请输入您要购买的商品序号(现在的优惠为"+type+")-现在总计为:"+price+"元,输入0结算--------------------"); Scanner scanner = new Scanner(System.in); int i = scanner.nextInt(); if(i==0){ break; } price+=product.get(i).getPrice(); System.out.println("购买成功 输入0结束购买"); } //最终价格 double result = CommodityFactory.getResult(price); System.out.println("实际付款"+result+"元"); } } 7.查看结果 D:\java\jdk\bin\java.exe "-javaagent:D:\idea\IntelliJ IDEA 2018.2.1\lib\idea_rt.jar=4289:D:\idea\IntelliJ IDEA 2018.2.1\bin" -Dfile.encoding=UTF-8 -classpath D:\java\jdk\jre\lib\charsets.jar;D:\java\jdk\jre\lib\deploy.jar;D:\java\jdk\jre\lib\ext\access-bridge-64.jar;D:\java\jdk\jre\lib\ext\cldrdata.jar;D:\java\jdk\jre\lib\ext\dnsns.jar;D:\java\jdk\jre\lib\ext\jaccess.jar;D:\java\jdk\jre\lib\ext\jfxrt.jar;D:\java\jdk\jre\lib\ext\localedata.jar;D:\java\jdk\jre\lib\ext\nashorn.jar;D:\java\jdk\jre\lib\ext\sunec.jar;D:\java\jdk\jre\lib\ext\sunjce_provider.jar;D:\java\jdk\jre\lib\ext\sunmscapi.jar;D:\java\jdk\jre\lib\ext\sunpkcs11.jar;D:\java\jdk\jre\lib\ext\zipfs.jar;D:\java\jdk\jre\lib\javaws.jar;D:\java\jdk\jre\lib\jce.jar;D:\java\jdk\jre\lib\jfr.jar;D:\java\jdk\jre\lib\jfxswt.jar;D:\java\jdk\jre\lib\jsse.jar;D:\java\jdk\jre\lib\management-agent.jar;D:\java\jdk\jre\lib\plugin.jar;D:\java\jdk\jre\lib\resources.jar;D:\java\jdk\jre\lib\rt.jar;D:\ideaWorkSpace\20190109\springboot_ueditor\target\classes com.huangfu.TestMain 1:超大冰淇淋 价格100.0 2:风扇 价格89.0 3:口香糖 价格32.5 4:卫龙 价格55.2 5:大面筋 价格215.0 6:超大鱿鱼 价格1000.5 7:八爪鱼酱 价格55.5 8:小熊饼干 价格66.6 -------------------请输入您要购买的商品序号(现在的优惠为满300返100)-现在总计为:0.0元,输入0结算-------------------- 1 购买成功 输入0结束购买 1:超大冰淇淋 价格100.0 2:风扇 价格89.0 3:口香糖 价格32.5 4:卫龙 价格55.2 5:大面筋 价格215.0 6:超大鱿鱼 价格1000.5 7:八爪鱼酱 价格55.5 8:小熊饼干 价格66.6 -------------------请输入您要购买的商品序号(现在的优惠为满300返100)-现在总计为:100.0元,输入0结算-------------------- 1 购买成功 输入0结束购买 1:超大冰淇淋 价格100.0 2:风扇 价格89.0 3:口香糖 价格32.5 4:卫龙 价格55.2 5:大面筋 价格215.0 6:超大鱿鱼 价格1000.5 7:八爪鱼酱 价格55.5 8:小熊饼干 价格66.6 -------------------请输入您要购买的商品序号(现在的优惠为满300返100)-现在总计为:200.0元,输入0结算-------------------- 1 购买成功 输入0结束购买 1:超大冰淇淋 价格100.0 2:风扇 价格89.0 3:口香糖 价格32.5 4:卫龙 价格55.2 5:大面筋 价格215.0 6:超大鱿鱼 价格1000.5 7:八爪鱼酱 价格55.5 8:小熊饼干 价格66.6 -------------------请输入您要购买的商品序号(现在的优惠为满300返100)-现在总计为:300.0元,输入0结算-------------------- 0 实际付款200.0元 Process finished with exit code 0 8.总结 策略模式中封装了变化,在官方定义上,策略模式就是用来封装算法的,可是在实际的业务场景中,策略模式几乎可以封装任何类型的规则。在业务分析中,只要应用到"在不同的时间应用不同的规则"这句话几乎都可以使用到策略模式,就比如上面那个例子,日后商场再增加任何算法,只需要再新增算法种类并继承优惠接口就可以了,当然需要更改工厂方法里面的switch语句(任何方法的改动都需要付出代价,后面会提到改进方法,提示:反射)就可以了,每一种算法都封装到一个类中,满足功能单一性,而且每个类负责一个算法不宜出错;所有算法继承同一个接口,方便日后的扩展,何乐而不为呢?本次就到这了,下期见!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-02-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA程序狗 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档