您的位置:首页 > 其它

设计模式之策略模式

2017-06-30 00:00 169 查看
译文原文出自:Strategy Design Pattern

策略模式属于行为设计模式中的一种,能够让我们在程序运行时选择实现特定的算法或者任务---同一任务可以有多种其他不同的实现。

重要之处在于,这些具体的实现之间是可以相互交换改变的---因为他们都是基于相同任务的实现,能够在不扰乱应用正常工作流的情况下改变实现。

本文的主要内容:

简介

设计参与者

问题描述

使用策略模式的解决方案

代码实现

代码演示

通用的实现

总结

简介

策略模式涉及从一个主类中去除具体的算法实现,把这些实现放在一个分离的类中。这样一来,在相同的程序上下文中,可能会有不同的算法实现(换句话说,不同的策略),能够在运行时选择。

策略模式保证一个客户端程序能选择来自一个算法族但是不同的算法,同时给出一种简单的方法可以在运行时候根据客户端的上下文,选择该算法的任何实现。

由开闭原则驱动

策略模式基于开闭原则。代码里面,我们不能修改上下文(对修改关闭),但是可以选择和增加任何实现(对扩展开放)。

举例来说,在Java中的 Collections.sort() --- 我们不能修改 sort() 方法来实现不同方式的排序。我们只能通过在运行时提供不同的 比较器(comparators)。

阅读更多关于比较器的内容请参考:比较器示例

设计参与者

在策略模式中,我们首先创建一个抽象的算法。抽象的算法是一个接口,包含抽象的操作。然后,我们创建这个抽象算法的具体实现,这些具体的实现叫作策略。

在客户端,总是调用抽象算法,调用的同时传递一个上下文对象。这个上下文对象将决定客户端使用何种具体的策略。



策略模式参与者

问题描述

让我们通过解决一个设计问题来更详细地理解策略模式。

我需要设计一个社交应用,可以允许我在不同的社交平台上连接我的朋友,比如Facebook,Google Plus,Twitter和Orkut(最后一个虚构,举例需要)。现在,我想要客户端能够告诉我,在我想要的那个平台朋友的名字,然后通过应用透明地连接到朋友。

更重要的是,如果我想要加入更多社交平台的信息到应用中,应用的现有的代码应该可以适应改变,不会影响已有的设计。

使用策略模式的解决方案

在上述问题中,我们可以通过多种方式进行同样的操作(连接朋友),同时用户可以在运行时选择所需的方式。策略模式刚好是一个不错的选择。

为了处理提出的问题,让我们首先设计好参与者:

ISocialMediaStrategy – 包含抽象操作的接口

SocialMediaContext – 决定使用何种实现的上下文

Implementations – ISocialMediaStrategy 的不同的具体实现策略。例如:FacebookStrategy, GooglePlusStrategy, TwitterStrategy and OrkutStrategy。

类图



策略模式类图

代码实现

现在,让我们编码实现上面的参与者们:

ISocialMediaStrategy.java

package com.howtodoinjava.designpattern.strategy;
public interface ISocialMediaStrategy
{
public void connectTo(String friendName);
}

SocialMediaContext.java

package com.howtodoinjava.designpattern.strategy;
public class SocialMediaContext
{
ISocialMediaStrategy smStrategy;
public void setSocialmediaStrategy(ISocialMediaStrategy smStrategy)
{
this.smStrategy = smStrategy;
}
public void connect(String name)
{
smStrategy.connectTo(name);
}
}

FacebookStrategy.java

package com.howtodoinjava.designpattern.strategy.impl;
import com.howtodoinjava.designpattern.strategy.ISocialMediaStrategy;
public class FacebookStrategy implements ISocialMediaStrategy {
public void connectTo(String friendName)
{
System.out.println("Connecting with " + friendName + " through Facebook");
}
}

GooglePlusStrategy.java

package com.howtodoinjava.designpattern.strategy.impl;
import com.howtodoinjava.designpattern.strategy.ISocialMediaStrategy;
public class GooglePlusStrategy implements ISocialMediaStrategy {
public void connectTo(String friendName)
{
System.out.println("Connecting with " + friendName + " through GooglePlus");
}
}

TwitterStrategy.java

package com.howtodoinjava.designpattern.strategy.impl;
import com.howtodoinjava.designpattern.strategy.ISocialMediaStrategy;
public class TwitterStrategy implements ISocialMediaStrategy {
public void connectTo(String friendName)
{
System.out.println("Connecting with " + friendName + " through Twitter");
}
}

OrkutStrategy.java

package com.howtodoinjava.designpattern.strategy.impl;
import com.howtodoinjava.designpattern.strategy.ISocialMediaStrategy;
public class OrkutStrategy implements ISocialMediaStrategy {
public void connectTo(String friendName)
{
System.out.println("Connecting with " + friendName + " through Orkut [not possible though :)]");
}
}


代码演示

现在让我们看看这些策略是如何在运行的时候被使用的:

package com.howtodoinjava.designpattern.strategy.demo;

import com.howtodoinjava.designpattern.strategy.SocialMediaContext;
import com.howtodoinjava.designpattern.strategy.impl.FacebookStrategy;
import com.howtodoinjava.designpattern.strategy.impl.GooglePlusStrategy;
import com.howtodoinjava.designpattern.strategy.impl.OrkutStrategy;
import com.howtodoinjava.designpattern.strategy.impl.TwitterStrategy;

public class Demo {
public static void main(String[] args) {
// Creating social Media Connect Object for connecting with friend by
// any social media strategy.
SocialMediaContext context = new SocialMediaContext();

// Setting Facebook strategy.
context.setSocialmediaStrategy(new FacebookStrategy());
context.connect("Lokesh");
System.out.println("====================");

// Setting Twitter strategy.
context.setSocialmediaStrategy(new TwitterStrategy());
context.connect("Lokesh");
System.out.println("====================");

// Setting GooglePlus strategy.
context.setSocialmediaStrategy(new GooglePlusStrategy());
context.connect("Lokesh");
System.out.println("====================");

// Setting Orkut strategy.
context.setSocialmediaStrategy(new OrkutStrategy());
context.connect("Lokesh");
}
}

输出结果:

Connecting with Lokesh through Facebook
====================
Connecting with Lokesh through Twitter
====================
Connecting with Lokesh through GooglePlus
====================
Connecting with Lokesh through Orkut [not possible though :)]


通用的实现

1.Java中的 Collections.sort(list, comparator) 方法,客户端实际传递一个满足实际运行时要求的比较器给sort方法,sort方法中的泛型参数可以接受任何的比较器类型。通过传递不同的比较器,可以对同样的数据集合进行不同的排序处理。

2.在 Log4j 中的Appenders, Layouts and Filters,有文件Appender,控制台Appenders等等。

3.UI toolkits中的布局管理器。

总结

1.策略模式定义一个相关算法的集合,把不同的算法实现封装在分离的类文件中,并且客户端在运行时选择任何具体的算法实现。

2.策略模式允许在不修改已有算法类或上下文类的前提下,增加一个新的算法实现,即使用算法或策略。

3.策略模式在Gof《设计模式》一书的设计模式列表分类中,属于行为模式。

4.策略模式思想是基于SOLID原则中开闭原则(Open Closed design principle)。

5.Java中的 Collections.sort() 和 Comparator接口的组合是策略模式应用的一个不错的栗子。

这就是所有关于策略模式的内容,欢迎在评论区留下你的问题。

示例源码下载

祝学习快乐!!

>>>>>译者补充内容>>>>>

何谓SOLID原则:

单一职责原则(Single Responsibility)

开闭原则(Open Closed)

里氏代换原则(Liskov Substitution)

接口隔离原原则(Interface Segregation)

依赖倒置原则(Dependency Inversion)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息