设计模式系列(一)——策略模式

概念:   

      策略模式做为一种软件设计模式,指对象有某个行为,可是在不一样的场景中,该行为有不一样的实现算法。(维基百科)java

理解概念:

      概念中说策略模式是某个行为在不一样场景下有不一样的实现算法。咱们知道有一条设计原则是这样的:分离变化的部分和不变的部分。在这个概念中咱们能够知道。不变的地方,是这个行为,变化的,是执行这个行为所须要的算法,或者说是策略。算法

应用场景:

      这个模式的应用场景应该是这样的。咱们须要对若干个均可以实现咱们所要的功能中选择一个最合适的。举一个简单的例子:java君、Pascal君、Scala君三我的要去餐厅吃饭。但是呢,他们仨我的的口味不同,java君想吃面向对象大餐,Pascal君想吃面向过程大餐,而Scala君想吃函数式大餐,这时候假设你是餐厅服务员,你给每一个人点餐的时候,就要这样写了spring

if(pascal君) return 面向过程大餐;else 
if(java君)return 面向对象大餐;else
if(scala君)return 函数式大餐;

这就太糟了。由于若是又来了一个spring先生想要吃aop大餐,就要去更改源码了。这不符合咱们“对修改关闭,对扩展开放”的原则。因此这种设计是不行的。编程

 

解决之道:

      咱们说要分离开变化的和不变的东西。变化的就是对不一样的人要上不一样的菜。咱们把这一点从代码中分离出来。单独封装起来。利用多态,给每一类人一个点某种菜的能力。咱们可让全部人实现一个Order接口,这个接口中定义了点菜这个方法,让每一个人都去实现这个方法,而后在点菜的时候直接去调用每一个人的order方法。这样若是在来新的人的话,咱们不用改动原有的代码,只须要让新人实现本身的order方法就能够。这样就符合设计原则了。下面是实现代码。设计模式

/*
 * Created by 王镜鑫 on 2016/10/7
 */
interface Order//点餐接口
{
    public void order();//点餐方法
}
class JAVA implements Order//java君实现点餐接口
{
    public void order()
    {
        System.out.println("I want a Object Oriented meal");
    }
}
class Pascal implements Order//Pascal君实现点餐接口
{
    public void order()
    {
        System.out.println("I want a Procedure Oriented meal");
    }
}
class Scala implements Order//Scala君实现点餐接口
{
    public void order()
    {
        System.out.println("I want a functional meal");
    }
}
public class Restaurant//餐厅
{
    private Order order = null;
    public void setOrder(Order order)//设置点餐的人。
    {
        this.order = order;
    }
    public void order()//让点餐人点餐
    {
        order.order();
    }

    public static void main(String[] args)
    {
        Restaurant restaurant = new Restaurant();//实例化一个餐厅
        restaurant.setOrder(new JAVA());//将java君设置进去
        restaurant.order();//让java君点餐
        restaurant.setOrder(new Pascal());//将Pascal君设置进去
        restaurant.order();//让Pascal君点餐
        restaurant.setOrder(new Scala());//将Scala君设置进去
        restaurant.order();//让Scala君点餐
    }
}

输出以下:函数

I want a Object Oriented meal
I want a Procedure Oriented meal
I want a functional meal

可见,java君、Pascal君、Scala君都吃到了本身想吃的大餐。而且及时再来一个汇编先生,咱们也不怕,也不用修改原来的代码。只须要在添加一个汇编先生类让其实现点餐接口就能够了。this

提炼总结:

      咱们经过一个例子。来描述了所谓的策略模式的应用场景,和如何应用策略模式解决问题,使代码更易扩展,下降耦合。下面咱们总结一下策略模式。
      经过上面的例子,咱们得知,策略模式包含如下角色:spa

  •   Context:上下文类,起到承上启下的封装做用,屏蔽上层模块对策略的直接访问。
  •   Strategy:抽象策略类。一般是一个抽象(接口或者抽象类)定义每一个策略中的必须有的方法和属性。
  •   ConcreteStrategy:具体策略类,是具体策略的实现。

三者的关系以下图:scala

上下文中有一个策略属性,还有一个设置策略的方法,一个工做方法。工做方法中实现的就是策略的工做方法。 具体的策略A和具体的策略B去实现了策略接口,实现了work方法。这样在调用上下文的work方法,就是调用了实际设置的具体策略的work方法,从而实现了将执行策略与具体的策略解耦,有新的策略的时候,只须要再从新声明一个策略类就能够。
      策略模式是一种很是简单的设计模式,策略模式是对不一样的算法的封装,把算法的责任和算法自己分离开来,将算法委派给不一样的对象管理,用一句话来讲,策略模式就是:实现一族算法,并将每个算法都封装起来,使其相互交换。
      策略模式中,使用哪种策略是由用户来决定的,这提升了系统的灵活性,可是这在必定程度上,也增长了客户端的使用难度。由于客户端须要了解不一样的算法之间的区别,选择合适的算法。策略模式还体现了这样一个设计原则:针对接口编程,而不是针对实现编程。咱们在策略模式中,用一个接口表明行为,根据多态,上下文在工做时执行的行为,是这个接口的具体实现。思考咱们经常使用的jdk官方的排序方法。Colloctions.sort(List<T> list)和他的重载方法 sort(List<T> list, Comparator<? super T> c)他们的实现都是直接调用了List的sort方法,区别是一个传入的比较器是null,一个是传入了具体的比较器,比较器是null的那个方法,list中的元素T也是实现了Comparablel接口的。这就是一个典型的策略模式的应用。再排序的时候,因为不一样的须要排序的类的排序规则不同,也就是策略不同,因此咱们把策略封装到客户部分,也就是具体须要排序的类中,也就是让具体须要排序的类实现Comparable接口,而后在传入到排序的算法中的时候,排序的算法在比较两个元素的前后顺序的时候直接调用其compareTo方法,根据多态,他调用的实际上是具体传入的compareTo方法。也就是封装到子类中的具体的比较策略,这样就能实现了具体的排序。这是策略模式在排序中的应用。
因为知识水平有限,文章中有疏漏或者错误的地方,欢迎你们留言指正。设计

相关文章
相关标签/搜索