Java设计模式之-策略模式(Strategy)

这个模式,怎么说呢,听名字真的很唬人,但是实际上,就是简单地用一个接口进行方法的抽象......
但是关键是这个模式想要传达的思想:
在制定策略时,将策略的具体实现与调用者解耦,且策略间可灵活互换。
我们还是来看一下设计模式一书是怎么描述策略模式的意图的:

Define a family of algorithms, encapsulate each one, and make theminterchangeable. Strategy lets the algorithm vary independently fromclients that use it.

所以策略模式要解决的是一个思维上的抽象过程,而非提出一个具体的且灵性的解决方案(solution)。


策略模式

大家看这个类图其实很简单,三个类实现一个接口,调用者使用接口中定义的方法。

关于策略模式其实没有特殊的需要说明的,但是它可以被用来进行除了上一篇模板方法模式提到的之外,另一种钩子方法的实现方式。

我们在Context中需要定义一个Strategy的变量,但是试想我们将变量的具体类放在调用时再确定,这个时候我们应该如何实例化strategy呢?这个时候我们需要一个空对象(Null Object)

//Null Object
public class NullStrategy{
    public void strategyInterface(){
        //do nothing...
    }
}

而在Context里的实现中,我们用NullStrategy来实例化strategy:

public class Context{
    private Strategy strategy = new NullStrategy();
    public Context(){}
    public void contextInterface(){
        strategy.strategyInterface();
    }

    public void setStrategy(Strategy s){
        this.strategy = s;
    }
}

由于有了setStrategy这个方法,我们可以将最终确定实现策略的子类确定时间延后到使用时刻。

public static void main(String[] args){
    Context context = new Context();
    context.contextInterface(); //do nothing...
    context.setStrategy(new ConcreteStrategyB());
    context.contextInterface(); //do ConcreteStrategyB.strategyInterface()
}

而这个setStrategy则成为了我们在代码中留出的一个钩子,增强了类的灵活性。
另外在类中使用一个不做任何事的子类来进行实例化,其实也算是一种设计模式,只不过没有在GoF的书中提到。


附:Null Object模式

在设计实现中,很多地方都用到了Null Object设计模式。 Null Object提供了“什么也不做”的行为,隐藏来自它的合作者的细节。对于如何理解和应用该模式,通过一个实例就能很好的进行说明。这一节我们在讨论消息分派器,消息分派器使用了前述的日志记录器,并且通过属性来注入具体的日志记录器对象。

private ILogger logger;
public void setLogger(ILogger value){
    this.logger = value;
}

现在假设,我们在消息分派器内部的多个地方使用日志记录器来进行日志记录,我们总要写这样的语句:

if (logger != null){
    logger.Log(); //记录日志
}

也就是说,在使用之前,我们都要判断一下日志记录器的引用是否为空,如果不为空才可以调用其Log方法。如果调用日志记录器进行日志记录的地方很多,那么每个地方都会充斥着这种判断其引用是否为空的代码。有没有办法来避免这所有的判断语句了,有!那就是使用Null Object设计模式。

为每种必要的组件都提供了对应的Null Object类型,这些类型的名字以“Empty”作为前缀。比如ILogger对应的Null Object类型就是EmptyLogger,EmptyLogger实现的Log方法什么也不用做:

public void Log(string errorType ,string msg, string location, ErrorLevel level){
    //Do Nothing !
}

有了EmptyLogger,我们就可以象这样来设计消息分派器的日志记录器属性:

private ILogger logger = new EmptyLogger();

public void setLogger(ILogger value){
    if (value != null){
        logger = value;
    }
}

如此一来,在消息分配器内部,我们就可以非常方便的直接使用日志记录器,而不用再判断其引用是否为空,因为无论如何,它总是指向一个有效的对象,即使这个对象是Null Object。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,573评论 18 399
  • 一. Java基础部分.................................................
    wy_sure阅读 3,788评论 0 11
  • 1 场景问题# 1.1 报价管理## 向客户报价,对于销售部门的人来讲,这是一个非常重大、非常复杂的问题,对不同的...
    七寸知架构阅读 5,035评论 9 62
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,717评论 2 17