23种设计模式图解csdn(程序猿设计模式系列之)
23种设计模式图解csdn(程序猿设计模式系列之)2、客户端方便根据外部条件选择不同的策略来解决不同的问题。 1、算法可独立于使用外部而变化定义一系列算法,将每一个算法封装到具有公共接口的一系列策略类中,,并让它们可以相互替换;策略模式让算法独立于使用它的客户而变化.作用将算法的责任和本身进行解耦,使得:
概述
1、策略模式是一种行为型设计模式中的一种.
2、它是定义一系列的算法,将每个算法封装起来,并使得他们可以相互替换,让算法独立于使用它的客户而变化,一般来用于替换if-else.
定义
定义一系列算法,将每一个算法封装到具有公共接口的一系列策略类中,,并让它们可以相互替换;策略模式让算法独立于使用它的客户而变化.
作用
将算法的责任和本身进行解耦,使得:
1、算法可独立于使用外部而变化
2、客户端方便根据外部条件选择不同的策略来解决不同的问题。
(策略模式仅仅封装算法(包含添加&删除),但策略模式并不决定在何时使用何种算法,算法的选择由客户端来决定)
角色
策略模式一般是有3种角色:
1、Context:上下文环境类,持有抽象策略角色的引用(实例),并负责调用相关的算法.
2、Strategy:策略接口或者策略抽象类,定义一系列抽象的算法策略.
3、ConcreteStrategy:具体策略类,实现具体的算法策略.
场景
1、一个系统需要动态底在几种算法中选择一种情况
2、系统里面有许多类,它们之间的区别仅在于行为,使用策略模式可以地让一个对象在许多行为中选择一种行为
3、一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重条件选择语句来实现。此时,使用策略模式,
将这些行为转移到相应的具体的策略类里面,就可以避免使用难以维护的多重条件选择语句
4、不希望客户端知道复杂的、与算法相关的数据结构,在具体策略类中封装算法与相关的数据结构,可以提高算法的保密性与安全性。
案例
a. 实例概况
背景:小成有一家百货公司,最近在定年度的促销活动
冲突:每个节日用同一个促销活动太枯燥,没吸引力
解决方案:针对不同节目使用不同促销活动进行促销
b. 使用步骤
步骤1: 定义抽象策略角色(Strategy):百货公司所有促销活动的共同接口。
abstract class Strategy {
publicabstractvoidShow();
}
步骤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;
}
}
publicvoidSalesManShow(){
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抽象类实现,而不能使用接口。
这其实也是典型的将代码向继承等级结构的上方集中的标准做法。
欢迎大家关注我的公众号:java学习之路,长期分享各种技术文章