暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

《程序猿设计模式系列》之 策略模式

JAVA的学习之路 2021-03-01
190

概述

1、策略模式是一种行为型设计模式中的一种.
2、它是定义一系列的算法,将每个算法封装起来,并使得他们可以相互替换,让算法独立于使用它的客户而变化,一般来用于替换if-else.

定义

定义一系列算法,将每一个算法封装到具有公共接口的一系列策略类中,,并让它们可以相互替换;策略模式让算法独立于使用它的客户而变化.

作用

将算法的责任和本身进行解耦,使得:

     1、算法可独立于使用外部而变化

     2、客户端方便根据外部条件选择不同的策略来解决不同的问题。

(策略模式仅仅封装算法(包含添加&删除),但策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定)


角色

      策略模式一般是有3种角色:

       1、Context:上下文环境类,持有抽象策略角色的引用(实例),并负责调用相关的算法.

      2、Strategy:策略接口或者策略抽象类,定义一系列抽象的算法策略.

      3、ConcreteStrategy:具体策略类,实现具体的算法策略.

场景

1、一个系统需要动态底在几种算法中选择一种情况
2、系统里面有许多类,它们之间的区别仅在于行为,使用策略模式可以地让一个对象在许多行为中选择一种行为
3、一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重条件选择语句来实现。此时,使用策略模式,
   将这些行为转移到相应的具体的策略类里面,就可以避免使用难以维护的多重条件选择语句
4、不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法与相关的数据结构,可以提高算法的保密性与安全性。

案例

a. 实例概况
   背景:小成有一家百货公司,最近在定年度的促销活动
   冲突:每个节日用同一个促销活动太枯燥,没吸引力
   解决方案:针对不同节目使用不同促销活动进行促销


b. 使用步骤
    步骤1: 定义抽象策略角色(Strategy):百货公司所有促销活动的共同接口。
abstract class Strategy {
      public abstract void Show();
}

步骤2:定义具体策略角色(Concrete Strategy):每个节日具体的促销活动
//为春节准备的促销活动A
class StrategyA extends Strategy {
@Override
public void Show() {
System.out.println("为春节准备的促销活动A");
}
}


//为中秋节准备的促销活动B
class StrategyB extends Strategy {
@Override
public void Show() {
System.out.println("为中秋节准备的促销活动B");
}
}


//为圣诞节准备的促销活动C
class StrategyC extends Strategy {
@Override
public void Show() {
System.out.println("为圣诞节准备的促销活动C");
}
}



步骤3:定义环境角色(Context):用于连接上下文,即把促销活动推销给客户,这里可以理解为销售员.
class Context_SalesMan {
//持有抽象策略角色的引用
private Strategy strategy;
public Context_SalesMan(String festival) {
switch (festival) {
case "A":
strategy = new StrategyA();
break;
case "B":
strategy = new StrategyB();
break;
case "C":
strategy = new StrategyC();
break;
}
}


      public void SalesManShow() {
strategy.Show();
}
}



步骤4:客户端调用-让销售员进行促销活动的落地
public static void main(String[] args) {
Context_SalesMan mSalesMan;
//春节来了,使用春节促销活动
System.out.println("对于春节:");
mSalesMan = new Context_SalesMan("A");
mSalesMan.SalesManShow();


//中秋节来了,使用中秋节促销活动
System.out.println("对于中秋节:");
mSalesMan = new Context_SalesMan("B");
mSalesMan.SalesManShow();


//圣诞节来了,使用圣诞节促销活动
System.out.println("对于圣诞节:");
mSalesMan = new Context_SalesMan("C");
mSalesMan.SalesManShow();
}



结果输出
对于春节:
为春节准备的促销活动A
对于中秋节:
为中秋节准备的促销活动B
对于圣诞节:
为圣诞节准备的促销活动C

优缺点

优点:
1、定义一系列算法实现,实现让这些算法可相互替换,(策略类之间可以自由切换){策略模式提供了对“开闭原则”的完美支持,
  用户可以在不修改原有系统的基础上选择算法(策略),并且可以灵活地增加新的算法(策略)}
  由于策略类都实现一个接口,所以使它们之间可以自由切换
2、避免多重条件选择语句(if else),充分体现面向对象设计思想。
3、更好的扩展性(易于扩展)
  增加一个新的策略只需要添加一个具体的策略类即可,基本不需要改变原有的代码,符合“开闭原则”
缺点:
1、调用者必须了解每种策略的不同,自行选择使用哪个策略。{客户端必须之前所有的策略类,并自行决定使用哪一个策略类}
2、增加了对象数据,可使用享元模式在一定程度上减少对象的数量
3、只适合扁平的算法结构,在一个策略接口下,运行时只有一个算法被使用,这样就限制了算法的使用层级,使用时不能嵌套使用。


总结

1、策略模式的主要目的是将算法的定义与使用分开,也就是将算法的行为和环境分开.
2、动态改变算法(热插拔)
3、算法可以重用(模板方法中算法不可重用)


策略模式的重心:

策略模式的重心不是如何实现算法,而是如何组织、调用这些算法,从而让程序结构更灵活,具有更好的维护性和扩展性。

算法的平等性

策略模式一个很大的特点就是各个策略算法的平等性。对于一系列具体的策略算法,大家的地位都是一样的,正因为这个平等性,才能实现算法之间可以互相替换。所有的策略算法在实现上也是相互独立的。相互之间是没有依赖的。所以可以这样描述这一系列策略算法:策略算是相同行为的不同实现。

运行时策略的唯一性:

运行期间,策略模式在每一个时刻只能使用一个具体的策略实现对象,虽然可以动态地在不同的策略实现中切换,但是同时只能使用一个。

公有的行为:

经常见到的是,所有的具体策略类都有一些公有的行为。这时候,就应当把这些公有的行为放到共同的抽象策略角色Strategy类里面。当然这时候抽象策略角色必须要用Java抽象类实现,而不能使用接口。
这其实也是典型的将代码向继承等级结构的上方集中的标准做法。









- THE END -

作者简介

Mr.W

白天搬砖,晚上砌梦想。

相信每个人有故事,程序员更是有许多事故,书写最接地气的程序员故事,为大家找出更好的资料。



文章转载自JAVA的学习之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论