策略模式

策略模式(StrategyPattern)中体现了两个非常基本的面向对象设计的原则

1.封装变化的概念

2.编程中使用接口,而不是对接口的实现

•面向接口的编程

策略模式的定义

1.定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。

2.策略模式使这些算法在客户端调用它们的时候能够互不影响地变化

 

策略模式的意义

1.策略模式使开发人员能够开发出由许多可替换的部分组成的软件,并且各个部分之间是弱连接的关系。

2.弱连接的特性使软件具有更强的可扩展性,易于维护;更重要的是,它大大提高了软件的可重用性

 

策略模式的组成

1.抽象策略角色:策略类,通常由一个接口或者抽象类实现

2.具体策略角色:包装了相关的算法和行为

3.环境角色:持有一个策略类的引用,最终给客户端调用的。

 

策略模式的实现

1.策略模式的用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。

2.策略模式使得算法可以在不影响到客户端的情况下发生变化。使用策略模式可以把行为和环境分割开来。

3.环境类负责维持和查询行为类,各种算法则在具体策略中提供。由于算法和环境独立开来,算法的修改都不会影响环境和客户端


策略模式UML类图(图片来自百度图库)


策略模式的编写步骤

–1.对策略对象定义一个公共接口。

–2.编写策略类,该类实现了上面的公共接口

–3.在使用策略对象的类中保存一个对策略对象的引用。

–4.在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值。

实现例子1:

1.对策略对象定义一个公共接口

Strategy.java

public interface Strategy

{

       publicint calculate(int a, int b);

}

2.编写策略类,该类实现了上面的公共接口

AddStrategy.java

public class AddStrategy implements Strategy

{

       publicint calculate(int a, int b)

       {

              returna + b;

       }

}

SubtractStrategy .java

public class SubtractStrategy implementsStrategy

{

       publicint calculate(int a, int b)

       {

              returna - b;

       }

 

}

 MultiplyStrategy.java

public class MultiplyStrategy implements Strategy

{

       publicint calculate(int a, int b)

       {

              returna * b;

       }

}

DivideStrategy.java

public class DivideStrategy implementsStrategy

{

       publicint calculate(int a, int b)

       {

              returna / b;

       }

}

以上分别实现加减乘除的四种策略

 

3.在使用策略对象的类中保存一个对策略对象的引用。

 

Environment.java

public class Environment

{

       privateStrategy strategy;

      

}

4.在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值

 

Environment.java

public class Environment

{

       privateStrategy strategy;

      

       publicEnvironment(Strategy strategy)

       {

              this.strategy= strategy;

       }

 

       publicStrategy getStrategy()

       {

              returnstrategy;

       }

 

       publicvoid setStrategy(Strategy strategy)

       {

              this.strategy= strategy;

       }

 

       publicint calculate(int a ,int b)

       {

              returnstrategy.calculate(a , b);

       }

}

测试:

Client.java

public class Client

{

       publicstatic void main(String[] args)

       {

              AddStrategy addStrategy = new AddStrategy();

 

              Environmentenvironment = new Environment(addStrategy);

 

              System.out.println(environment.calculate(3,4));

 

              SubtractStrategysubtractStrategy = new SubtractStrategy();

 

              environment.setStrategy(subtractStrategy);

 

              System.out.println(environment.calculate(3,4));

 

              MultiplyStrategy multiplyStrategy = new MultiplyStrategy();

 

              environment.setStrategy(multiplyStrategy);

 

              System.out.println(environment.calculate(3,4));

 

              DivideStrategy divideStrategy = new DivideStrategy();

 

              environment.setStrategy(divideStrategy);

 

              System.out.println(environment.calculate(3,4));

 

       }

}

实现例子2:

1.对策略对象定义一个公共接口

SortInterface.java

import java.util.List;

 

public interface SortInterface

{

       publicvoid sort(List<Person> list);

}

Person.java

public class Person

{

       privateint id;

      

       privateString name;

      

       privateint age;

 

       publicint getId()

       {

              returnid;

       }

 

       publicvoid setId(int id)

       {

              this.id= id;

       }

 

       publicString getName()

       {

              returnname;

       }

 

       publicvoid setName(String name)

       {

              this.name= name;

       }

 

       publicint getAge()

       {

              returnage;

       }

 

       publicvoid setAge(int age)

       {

              this.age= age;

       }

}

2.编写策略类,该类实现了上面的公共接口

DownNameSort .java

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

 

public class DownNameSort implementsSortInterface, Comparator<Person>

{

       publicvoid sort(List<Person> list)

       {

              Collections.sort(list, this);

       }

      

       publicint compare(Person o1, Person o2)

       {

              intresult = o2.getName().compareTo(o1.getName());

             

              if(0== result)

              {

                     returno1.getId() - o2.getId();

              }

             

              returnresult;

       }

 

}

UpNameSort .java

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

 

public class UpNameSort implementsSortInterface, Comparator<Person>

{

       publicvoid sort(List<Person> list)

       {

              Collections.sort(list,this);

       }

      

       publicint compare(Person o1, Person o2)

       {

              intresult = o1.getName().compareTo(o2.getName());

             

              if(0== result)

              {

                     returno1.getId() - o2.getId();

              }

             

              returnresult;

       }

}

3.在使用策略对象的类中保存一个对策略对象的引用。

4.在使用策略对象的类中,实现对策略对象的set和get方法(注入)或者使用构造方法完成赋值

Environment.java

import java.util.List;

 

public class Environment

{

       privateSortInterface sortInterface;

      

       publicEnvironment(SortInterface sortInterface)

       {

              this.sortInterface= sortInterface;

       }

      

       publicEnvironment()

       {

             

       }

 

       publicvoid setSortInterface(SortInterface sortInterface)

       {

              this.sortInterface= sortInterface;

       }

      

       publicvoid sort(List<Person> list)

       {

              this.sortInterface.sort(list);

       }

}

测试

Client.java

import java.util.ArrayList;

import java.util.List;

 

public class Client

{

       publicstatic void main(String[] args)

       {

              Personp1 = new Person();

              p1.setName("Tom");

              p1.setId(1);

              p1.setAge(20);

 

              Personp2 = new Person();

              p2.setName("Tonny");

              p2.setId(2);

              p2.setAge(50);

 

              Personp3 = new Person();

              p3.setName("Tom");

              p3.setId(5);

              p3.setAge(30);

 

              Personp4 = new Person();

              p4.setName("ABC");

              p4.setId(8);

              p4.setAge(10);

 

              Personp5 = new Person();

              p5.setName("Xyz");

              p5.setId(9);

              p5.setAge(15);

 

              List<Person>list = new ArrayList<Person>();

              list.add(p1);

              list.add(p2);

              list.add(p3);

              list.add(p4);

              list.add(p5);

 

              Environmentenv = new Environment();

 

              UpNameSortuns = new UpNameSort();

 

              env.setSortInterface(uns);

 

              env.sort(list);

 

              for(int i = 0; i < list.size(); i++)

              {

                     Personp = list.get(i);

 

                     System.out.println("id:" + p.getId() + ", name: " + p.getName()

                                   +", age:" + p.getAge());

              }

 

              System.out.println("--------------");

             

              DownNameSortdns = new DownNameSort();

 

              env.setSortInterface(dns);

              env.sort(list);

 

              for(int i = 0; i < list.size(); i++)

              {

                     Personp = list.get(i);

 

                     System.out.println("id:" + p.getId() + ", name: " + p.getName()

                                   +", age:" + p.getAge());

              }

 

       }

}

策略模式优缺点

优点:

1、简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试。 
2、避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展。 
3、遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。

缺点: 
1、因为每个具体策略类都会产生一个新类,所以会增加系统需要维护的类的数量。

2、在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象。(这本身没有解除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由Context来承担,这就最大化的减轻了客户端的压力。)

简单工厂模式和策略模式区别:

这两种模式的作用就是拥抱变化,减少耦合。在变化来临时争取做最小的改动来适应变化。这就要求我们把些“善变”的功能从客户端分离出来,形成一个个的功能类,然后根据多态特性,使得功能类变化的同时,客户端代码不发生变化。

简单工厂模式

简单工厂模式:有一个父类需要做一个运算(其中包含了不同种类的几种运算),将父类涉及此运算的方法都设成虚方法,然后父类派生一些子类,使得每一种不同的运算都对应一个子类。另外有一个工厂类,这个类一般只有一个方法(工厂的生成方法),这个方法的返回值是一个超类,在方法的内部,根据传入参数的不同,分别构造各个不同的子类的对象,并返回。客户端并不认识子类,客户端只认识超类和工厂类。每次客户端需要一中运算时,就把相应的参数传给工厂类,让工厂类构造出相应的子类,然后在客户端用父类接收(这里有一个多态的运用)。客户端很顺理成章地用父类的计算方法(其实这是一个虚方法,并且已经被子类特化过了,其实是调用子类的方法)计算出来结果。如果要增加功能时,你只要再从父类中派生相应功能的子类,然后修改下工厂类就OK了,对于客户端是透明的。

策略模式

策略模式:策略模式更直接了一点,没有用工厂类,而是直接把工厂类的生成方法的代码写到了客户端。客户端自己构造出了具有不同功能的子类(而且是用父类接收的,多态),省掉了工厂类。策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。这里的算法家族和简单工厂模式里的父类是同一个概念。当不同的行为堆砌在一个类中时,就很难避免使用条件语句来选择合适的行为,将这些行为封装在一个个独立的策略子类中,可以在客户端中消除条件语句。

简单工厂模式+策略模式:为了将工厂方法的代码从客户端移出来,我们把这些代码搬到了父类的构造函数中,让父类在构造的时候,根据参数,自己实现工厂类的作用。这样做的好处就是,在客户端不用再认识工厂类了,客户端只要知道父类一个就OK,进一步隔离了变化,降低了耦合。

在基本的策略模式中,选择所用具体实现的职责由客户端对象成端,并转给客户端。这本身并没有减除客户端需要选择判断的压力,而策略模式与简单工厂模式结合后,选择具体实现的职责也可以由父类承担,这就最大化地减轻了客户端的职责


策略模式在jdk中的应用

ThreadPoolExecutor中的四种拒绝策略(

  1. 在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时RejectedExecutionException
  2. 在 ThreadPoolExecutor.CallerRunsPolicy 中,线程调用运行该任务的execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
  3. 在 ThreadPoolExecutor.DiscardPolicy 中,不能执行的任务将被删除。
  4. 在 ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。
)


java.util.Comparator#compare()
javax.servlet.http.HttpServlet
javax.servlet.Filter#doFilter() 

策略模式在spring中的应用:

Spring的代理方式有两个Jdk动态代理和CGLIB代理。这两个代理方式的使用正是使用了策略模式。

本文参考资料:http://inotgaoshou.iteye.com/blog/1014052

             http://www.cnblogs.com/syxchina/archive/2011/10/11/2207017.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值