经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
通俗易懂设计模式解析——策略模式
来源:cnblogs  作者:小世界的野孩子  时间:2019/10/16 12:03:45  对本文有异议

前言

  今天我们来看策略模式【Stragety Pattern【行为型】】,这个模式还是比较好理解的。策略怎么理解呢?一般是指:1. 可以实现目标的方案集合;2. 根据形势发展而制定的行动方针和斗争方法;3. 有斗争艺术,能注意方式方法。总的来说呢就是针对一个目的的不同的方法集合。这里要讲的策略模式怎么理解呢?简单的说就是对于一个类的行为或者其算法可以在运行时更改替换。

策略模式介绍

一、来由

  在软件系统中,一些对象使用的算法或者行为可能会经常变化,如果把这些变化的算法写到对象中的话,会使对象变得较为复杂、不易理解。那么我们如何在运行时动态的修改对象的不同的算法呢?这就使用到了策略模式。

二、意图

  定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

三、案例图

 

四、策略模式代码示例

  看上面的案例图好像和上一篇状态模式的案例图有点相似。都是包含的三个部分。具体区别我们看后面的详细介绍。

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

抽象策略:定义一个公共方法,由其具体策略去实现不同算法。

具体策略:实现抽象策略接口方法。

  这里我们看这么一个案例,在一个超市买东西。最后结算的时候都会问是否有会员,结算机制就有以下几种。普通用户全额计算。普通会员打95折。黄金会员打9折。钻石会员打8折。我们看下如何实现这一功能:

 

  1. namespace Stragety_Pattern
  2. {
  3. class StragetyPattern
  4. {
  5. }
  6. #region 抽象策略==================
  7. /// <summary>
  8. /// 抽象策略接口
  9. /// </summary>
  10. public interface IStragetyPattern
  11. {
  12. /// <summary>
  13. /// 结算接口
  14. /// </summary>
  15. void Settlement(decimal Money);
  16. }
  17. #endregion
  18.  
  19. #region 具体策略=======================
  20. /// <summary>
  21. /// 无会员计算方式
  22. /// </summary>
  23. public class OrdinaryStragety : IStragetyPattern
  24. {
  25. public void Settlement(decimal Money)
  26. {
  27. Console.WriteLine($"不是会员,不进行折扣结算。应付款{Money}");
  28. }
  29. }
  30. /// <summary>
  31. /// 普通会员计算方式
  32. /// </summary>
  33. public class MemberStragety : IStragetyPattern
  34. {
  35. public void Settlement(decimal Money)
  36. {
  37. Console.WriteLine($"普通会员,打95折结算。应付款{Money*0.9M}");
  38. }
  39. }
  40. /// <summary>
  41. /// 黄金会员计算方式
  42. /// </summary>
  43. public class GoldMemberStragety : IStragetyPattern
  44. {
  45. public void Settlement(decimal Money)
  46. {
  47. Console.WriteLine($"黄金会员,打9折结算。应付款{Money*0.95M}");
  48. }
  49. }
  50. /// <summary>
  51. /// 钻石会员计算方式
  52. /// </summary>
  53. public class DiamondGoldMemberStragety : IStragetyPattern
  54. {
  55. public void Settlement(decimal Money)
  56. {
  57. Console.WriteLine($"钻石会员,打8折结算。应付款{Money*0.8M}");
  58. }
  59. }
  60. #endregion
  61.  
  62. #region 环境角色
  63. public class ContextStragety
  64. {
  65. private IStragetyPattern _stragety;
  66. public ContextStragety(IStragetyPattern stragety)
  67. {
  68. _stragety = stragety;
  69. }
  70. /// <summary>
  71. /// 调用结算方法
  72. /// </summary>
  73. /// <param name="Money"></param>
  74. public void GetSettlement(decimal Money)
  75. {
  76. _stragety.Settlement( Money);
  77. }
  78. }
  79. #endregion
  80. }

 

  1. namespace Stragety_Pattern
  2. {
  3. class Program
  4. {
  5. static void Main(string[] args)
  6. {
  7. decimal Account = 190.99M;
  8. ///会员计算
  9. ContextStragety stragety = new ContextStragety(new MemberStragety());
  10. stragety.GetSettlement(Account);
  11. ///普通结算
  12. stragety = new ContextStragety(new OrdinaryStragety());
  13. stragety.GetSettlement(Account);
  14. }
  15. }
  16. }

  这里我们针对最后结算的金额进行计算的时候是可以相互替换的。因为在具体策略中,都把算法的变化封装了起来。

 使用场景及优缺点

一、使用场景

1、如果在系统中有一些类,他们之间的区别就在于其行为的话。可以使用策略模式让一个对象在许多的行为中动态的选择一种行为。

2、一个系统中需要在多种算法中选择一种。

3、如果一个对象有许多的行为的话,可以简化其多重条件选择语句。避免难于维护的问题。

二、优点

1、策略类之间可以自由切换,因为策略类中都是实现的抽象策略的一个方法。所以可以自由切换。

2、易于扩展,在我们新增策略的时候基本上不需要修改之前的代码。

3、对多重条件选择语句进行优化简化

三、缺点

1、随着策略增多,策略类会随之增加。

2、客户端必须知道所有的策略类,并且自行决定使用哪一种策略。

总结

  到这里策略模式就介绍完了。策略模式主要是针对的有一系列算法。并把他们都封装起来。他们之间可以自由切换。使这些算法的变化独立于客户端的变化。也就是把多种行为之间的变化分别进行封装起来。然后在我们调用的时候可以自由的进行切换调用。

  这里我们在开篇有提到策略模式的案例图和状态模式的有点相似。这里我们重点分析一些策略模式和状态模式之间的区别吧:

1、环境角色中的任务有所不同,策略模式的环境角色中具有一种委托作用,负责根据传进来的策略调用其算法。但是状态模式中的环境角色不仅负责这行为方法的调用,还负责有记录状态变化、与具体的状态类协作。完成状态切换之后行为的切换。

2、策略模式主要解决的问题是将内部的算法的改变对外部的影响降低。保证算法的自由切换。状态模式主要解决的是状态的改变引起行为的变化、一个对象状态改变,从外界看来就好像是行为改变。

3、策略模式是一个算法的封装。这里封装的一个算法可以是有意义的对象,也可以是没有意义的逻辑片段。例如这里封装加密算法。各种加密算法,可以自由切换。算法必须是平行的。状态模式是要求一些列的状态变化随着有着行为的变化。要求拥有状态和行为。


即使受伤了,也要抬起头微笑着说,今天天气真好。

   C#设计模式系列目录

   欢迎大家扫描下方二维码,和我一起踏上设计模式的闯关之路吧!

  

原文链接:http://www.cnblogs.com/hulizhong/p/11678188.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号