java策略模式的context_Java策略模式(Strategy模式) 之体验

本文探讨了Java策略模式中的Context角色,通过示例展示了如何在多个策略实现中利用Context进行安全性检查、参数管理和算法统计。通过引入Context,可以避免重复代码,灵活应对策略变化,并提供了一种在策略类中访问和使用上下文信息的方法。
摘要由CSDN通过智能技术生成

packagecom.icecode.demo;importcom.icecode.demo.strategy.AbstractStrategy;importcom.icecode.demo.strategy.impl.ConcreteStrategy1;importcom.icecode.demo.strategy.impl.ConcreteStrategy2;/*** 策略模式测试类

*@authorzhanche

**/

public classClient {/***@paramargs*/

public static voidmain(String[] args) {

AbstractStrategy strategy= newConcreteStrategy1();

strategy.algorithm();

strategy= newConcreteStrategy2();

strategy.algorithm();

}

}

输出结果如下:

----------------我是策略一算法----------------

----------------我是策略二算法----------------

可见,2种方案都实现了同一个引用根据不同的实现执行特定的算法。是的,分析发现,在上面简单的应用中,Context的确可以取消。那么,Context这个角色为什么还要存在呢?

让我们考虑以下几种情况:

1、如果我们需要对不同策略中相同算法的参数,执行相同的安全性检查,我们如果没有环境角色Context,则只能在每个实现的开始部分,调用安全性检查代码;而有了Context这个角色,我们可以在调用Context的构造器时,统一进行安全性检查。这在我们的实现策略比较多的时候,比如说7、8个的时候,特别有用,可以大量减少冗余的代码量。

2、如果我们需要改变原有算法时,需要引进新的参数,如果没有Context,我们怎么办?一种办法是重载该算法,增加新的函数接口;另外一种办法是完全废弃原有的函数接口,重新写新的函数接口。毋庸置疑,这2种办法的代价都很大,尤其是如果这个新的参数只有部分实现策略中的该算法实现用到的时候。而我们使用Context就可以完全解决这个问题。

下面我们改造下上面那个基本策略模式,我们让策略模式也持有对Context的引用,这样的优点是可以在策略类里回调的Context里的所有可用的变量或函数等信息。此外,我们也增加一个新的实现策略类ConcreteStrategy3,具体代码如下所示:

Java代码  2f8047ea84be54b2d76b8867fecb6ed1.png

packagecom.icecode.demo.strategy;importcom.icecode.demo.context.Context;/*** 抽象策略

*@authorzhanche

**/

public abstract classAbstractStrategy {/*** 某个希望有不同策略实现的算法*/

public abstract voidalgorithm(Context context);

}packagecom.icecode.demo.strategy.impl;importcom.icecode.demo.context.Context;importcom.icecode.demo.strategy.AbstractStrategy;/*** 对算法的第一种具体实现策略

*@authorzhanche

**/

public class ConcreteStrategy1 extendsAbstractStrategy {

@Overridepublic voidalgorithm(Context context) {

System.out.println("----------------我是策略一算法----------------");

}

}packagecom.icecode.demo.strategy.impl;importcom.icecode.demo.context.Context;importcom.icecode.demo.strategy.AbstractStrategy;/*** 对算法的第二种具体实现策略

*@authorzhanche

**/

public class ConcreteStrategy2 extendsAbstractStrategy {

@Overridepublic voidalgorithm(Context context) {

System.out.println("----------------我是策略二算法----------------");

}

}packagecom.icecode.demo.strategy.impl;importcom.icecode.demo.context.Context;importcom.icecode.demo.strategy.AbstractStrategy;/*** 对算法的第三种具体实现策略

*@authorzhanche

**/

public class ConcreteStrategy3 extendsAbstractStrategy {

@Overridepublic voidalgorithm(Context context) {

System.out.println("----------------我是策略三算法----------------");

}

}packagecom.icecode.demo.context;importcom.icecode.demo.strategy.AbstractStrategy;/*** 环境角色,主要完成对特定策略的调用

*@authorzhanche

**/

public classContext {/*** 持有对策略的引用*/

privateAbstractStrategy strategy;/*** 算法入口*/

public voidalgorithm() {this.strategy.algorithm(this);

}

}

好了,现在我们想这样改变需求,ConcreteStrategy2和ConcreteStrategy3里对algorithm算法的实现,需要统计两个新的信息,分别用parameter1和parameter2来表示,同时要统计所有实现策略类里,对algorithm算法调用的次数。

如果没有Context这个角色,又需要做到客户端调用的时候代码改动尽量少,相信大家的做法只好是改抽象策略类和实现策略类里的algorithm算法。但是这样实现策略ConcreteStrategy1可能不愿意了,因为他并不需要新增加的参数;此外,对所有实现类里algorithm算法调用的统计也没有一个统一的入口,需要在每个algorithm实现中,插入一个计数代码。但是如果有了环境角色Context,一切就变得很简单了,我们不需要改动抽象策略类,和实现策略类ConcreteStrategy1,只需要改需求发生变化相关的类,且看下面的代码:

Java代码  2f8047ea84be54b2d76b8867fecb6ed1.png

packagecom.icecode.demo.context;importcom.icecode.demo.strategy.AbstractStrategy;/*** 环境角色,主要完成对特定策略的调用

*@authorzhanche

**/

public classContext {/*** 持有对策略的引用*/

privateAbstractStrategy strategy;/*** parameter1、parameter2只是ConcreteStrategy2ConcreteStrategy3需要使用的参数,

* 而ConcreteStrategy1不使用*/

private intparameter1;private intparameter2;//count用来统计所有策略的算法algorithm调用的总次数

public static int count = 0;publicContext(AbstractStrategy strategy) {this.strategy =strategy;

}public Context(AbstractStrategy strategy, int parameter1, intparameter2) {super();this.strategy =strategy;this.parameter1 =parameter1;this.parameter2 =parameter2;

}public intgetParameter1() {returnparameter1;

}public intgetParameter2() {returnparameter2;

}/*** 算法入口*/

public voidalgorithm() {

count++;

System.out.println("------------这是第"+count+"次调用algorithm算法--------");this.strategy.algorithm(this);

}

}packagecom.icecode.demo.strategy.impl;importcom.icecode.demo.context.Context;importcom.icecode.demo.strategy.AbstractStrategy;/*** 对算法的第一种具体实现策略

*@authorzhanche

**/

public class ConcreteStrategy1 extendsAbstractStrategy {

@Overridepublic voidalgorithm(Context context) {

System.out.println("----------------我是策略一算法----------------");

}

}packagecom.icecode.demo.strategy.impl;importcom.icecode.demo.context.Context;importcom.icecode.demo.strategy.AbstractStrategy;/*** 对算法的第二种具体实现策略

*@authorzhanche

**/

public class ConcreteStrategy2 extendsAbstractStrategy {

@Overridepublic voidalgorithm(Context context) {

System.out.println("----------------我是策略二算法----------------");

System.out.println("------------------我需要的参数parameter1="+context.getParameter1());

System.out.println("------------------我需要的参数parameter2="+context.getParameter2());

}

}packagecom.icecode.demo.strategy.impl;importcom.icecode.demo.context.Context;importcom.icecode.demo.strategy.AbstractStrategy;/*** 对算法的第三种具体实现策略

*@authorzhanche

**/

public class ConcreteStrategy3 extendsAbstractStrategy {

@Overridepublic voidalgorithm(Context context) {

System.out.println("----------------我是策略二算法----------------");

System.out.println("------------------我需要的参数parameter1="+context.getParameter1());

System.out.println("------------------我需要的参数parameter2="+context.getParameter2());

}

}

客户端测试的代码如下:

Java代码  2f8047ea84be54b2d76b8867fecb6ed1.png

packagecom.icecode.demo;importcom.icecode.demo.context.Context;importcom.icecode.demo.strategy.impl.ConcreteStrategy1;importcom.icecode.demo.strategy.impl.ConcreteStrategy2;importcom.icecode.demo.strategy.impl.ConcreteStrategy3;/*** 策略模式测试类

*@authorzhanche

**/

public classClient {/***@paramargs*/

public static voidmain(String[] args) {

Context context= new Context(newConcreteStrategy1());

context.algorithm();

context= new Context(new ConcreteStrategy2(),100, 200);

context.algorithm();

context= new Context(new ConcreteStrategy3(), 100, 200);

context.algorithm();

}

}

测试输出结果如下:

------------这是第1次调用algorithm算法--------

----------------我是策略一算法----------------

------------这是第2次调用algorithm算法--------

----------------我是策略二算法----------------

------------------我需要的参数parameter1=100

------------------我需要的参数parameter2=200

------------这是第3次调用algorithm算法--------

----------------我是策略三算法----------------

------------------我需要的参数parameter1=100

------------------我需要的参数parameter2=200

由以上分析可见,策略模式中,各个角色的功能都非常重要,虽然环境角色Context可以在某些简单的策略模式中不去使用,但是如果无法预测到各个实现策略功能和需求的变化,以及实现灵活性更好的策略模式,在使用策略模式进行架构时,一定要充分利用所有角色的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值