java中策略模式深入分析及示例

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

–封装变化的概念
–编程中使用接口,而不是对接口的实现

策略模式的定义
–定义一组算法,将每个算法都封装起来,并且使它们之间可以互换。
–策略模式使这些算法在客户端调用它们的时候能够互不影响地变化

策略模式的编写步骤
–1.对策略对象定义一个公共接口。
–2.编写策略类,该类实现了上面的公共接口
–3.在使用策略对象的类中保存一个对策略对
象的引用。
–4.在使用策略对象的类中,实现对策略对象
的set和get方法(注入)或者使用构造方法完
成赋值

方案

把一个类中经常改变或者将来可能改变的部分提取出来,作为一个接口,然后在类中包含这个对象的实例,这样类的实例在运行时就可以随意调用实现了这个接口的类的行为。
比如定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换,使得算法可独立于使用它的客户而变化。这就是策略模式。

适用情况

许多相关的类仅仅是行为有异。 “策略”提供了一种用多个行为中的一个行为来配置一个类的方法。即一个系统需要动态地在几种算法中选择一种。
当一个应用程序需要实现一种特定的服务或者功能,而且该程序有多种实现方式时使用。

一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

优点

1、可以动态的改变对象的行为

缺点

1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类
2、策略模式将造成产生很多策略类

组成

环境类(Context):用一个ConcreteStrategy对象来配置。维护一个对Strategy对象的引用。可定义一个接口来让Strategy访问它的数据。
抽象策略类(Strategy):定义所有支持的算法的公共接口。 Context使用这个接口来调用某ConcreteStrategy定义的算法。
具体策略类(ConcreteStrategy):以Strategy接口实现某具体算法。

应用

场景如下,刘备要到江东娶老婆了,走之前诸葛亮给赵云三个锦囊妙计,说是按天机拆开能解决棘手问题。场景中出现三个要素:三个妙计(具体策略类)、一个锦囊(环境类)、赵云(调用者)。

 

 代码如下 复制代码

抽象策略类(Strategy)
public interface Strategy {
     public void operate();
}

三个实现类(ConcreteStrategy):
妙计一:初到吴国
public class BackDoor implements IStrategy {
     @Override
     public void operate() {
          System.out.println("找乔国老帮忙,让吴国太给孙权施加压力,使孙权不能杀刘备");
     }
}妙计二:求吴国太开绿灯放行
public class GivenGreenLight implements IStrategy {
     @Override
     public void operate() {
          System.out.println("求吴国太开个绿灯,放行");
     }
}妙计三:孙夫人断后,挡住追兵
public class BlackEnemy implements IStrategy {
     @Override
     public void operate() {
          System.out.println("孙夫人断后,挡住追兵");
     }
}
环境类(Context)
public class Context {
     private Strategy strategy;
     //构造函数,要你使用哪个妙计
     public Context(Strategy strategy){
          this.strategy = strategy;
     }
     public void setStrategy(Strategy strategy){
          this.strategy = strategy;
     }
     public void operate(){
          this.strategy.operate();
     }
}

例子

在使用图像处理软件处理图片后,需要选择一种格式进行保存。然而各种格式在底层实现的算法并不相同,这刚好适合策略模式。编写程序,演示如何使用策略模式与简单工厂模式组合进行开发
思路如下:

使用interface来定义一个接口,在该接口中定义save()方法;
根据图片格式定义不同的类,分别在这些类中使用关键字implements实现接口;
创建一个实现选择的类,在该类中定义实现选择的方法,该方法返回值为对应的图片保存类;
在主方法中实现接口。
代码如下:

 代码如下 复制代码

public interface ImageSaver {
    void save();//定义save()方法
}

public class GIFSaver implements ImageSaver {
    @Override
    public void save() {//实现save()方法
        System.out.println("将图片保存成GIF格式");
    }
}

public class JPEGSaver implements ImageSaver {

    @Override
    public void save() {
        System.out.println("将图片保存成JPG格式");
    }
}

public class PNGSaver implements ImageSaver {

    @Override
    public void save() {
        System.out.println("将图片保存成PNG格式");
    }

}

public class TypeChooser {
    public static ImageSaver getSaver(String type) {
        if (type.equalsIgnoreCase("GIF")) {//使用if else语句来判断图片的类型
            return new GIFSaver();
        } else if (type.equalsIgnoreCase("JPEG")) {
            return new JPEGSaver();
        } else if (type.equalsIgnoreCase("PNG")) {
            return new PNGSaver();
        } else {
            return null;
        }
    }
}

public class User {
    public static void main(String[] args) {
        System.out.print("用户选择了GIF格式:");
        ImageSaver saver = TypeChooser.getSaver("GIF");//获得保存图片为GIF类型的对象
        saver.save();
        System.out.print("用户选择了JPEG格式:");//获得保存图片为JPEG类型的对象
        saver = TypeChooser.getSaver("JPEG");
        saver.save();
        System.out.print("用户选择了PNG格式:");//获得保存图片为PNG类型的对象
        saver = TypeChooser.getSaver("PNG");
        saver.save();
    }
}

java排序策略模式实现:

有这样一个类:

 代码如下 复制代码

public class Person {

private int id;

private String name;

private int age;

}

要求:假如有若干个类Person对象存在一个List当中,对他们进行排序,分别按照名字、

年龄、id 进行排序(要有正序与倒序两种排序方式)。假如年龄或者姓名重复,按照id的正序进行排序。

以下为实现源代码。

 代码如下 复制代码

类Person

 package com.jack.SortStrategy;

public class Person {
 private int id;
 private String name;
 private int age;
 
 public Person(int id,String name,int age){
  this.id=id;
  this.age=age;
  this.name=name;
 }
 /**
  * @return the id
  */
 public int getId() {
  return id;
 }
 /**
  * @param id the id to set
  */
 public void setId(int id) {
  this.id = id;
 }
 /**
  * @return the name
  */
 public String getName() {
  return name;
 }
 /**
  * @param name the name to set
  */
 public void setName(String name) {
  this.name = name;
 }
 /**
  * @return the age
  */
 public int getAge() {
  return age;
 }
 /**
  * @param age the age to set
  */
 public void setAge(int age) {
  this.age = age;
 }
}
类IdOrder

package com.jack.SortStrategy;

import java.util.Comparator;

public class IdOrder implements Comparator<Person> {

 @Override
 public int compare(Person o1, Person o2) {
  // TODO Auto-generated method stub
  return o1.getId()-o2.getId();
 }
 public String getMethodName()
 {
  return "按id正序";
 }

}
类IdReverseOrder

package com.jack.SortStrategy;

import java.util.Comparator;

public class IdReverseOrder implements Comparator<Person> {
 
 @Override
 public int compare(Person o1, Person o2) {
  // TODO Auto-generated method stub
  return o2.getId()-o1.getId();
 }
 public String getMethodName()
 {
  return "按id逆序";
 }
}
类AgeOrder

package com.jack.SortStrategy;

import java.util.Comparator;

public class AgeOrder implements Comparator<Person> {

 @Override
 public int compare(Person o1, Person o2) {
  // TODO Auto-generated method stub
  int result=o1.getAge()-(o2.getAge());
  if(0==result){                                      //若年龄相同按id排
   return o1.getId()-o2.getId();
  }
  return result;
 }
 public String getMethodName()
 {
  return "按年龄正序";
 }
}
类AgeReverseOrder

package com.jack.SortStrategy;

import java.util.Comparator;

public class AgeReverseOrder implements Comparator<Person> {
 
 @Override
 public int compare(Person o1, Person o2) {
  // TODO Auto-generated method stub
  int result=o2.getAge()-(o1.getAge());
  if(0==result){                                      //若年龄相同按id排
   return o1.getId()-o2.getId();
  }
  return result;
 }
 public String getMethodName()
 {
  return "按年龄逆序";
 }
}
类NameOrder

package com.jack.SortStrategy;

import java.util.Comparator;

public class NameOrder implements Comparator<Person> {

 @Override
 public int compare(Person o1, Person o2) {
  // TODO Auto-generated method stub
  int result=o1.getName().compareTo(o2.getName());
  if(0==result){                                                              //若姓名相同按id排
   return o1.getId()-o2.getId();
  }
  return result;
 }
 public String getMethodName()
 {
  return "按姓名正序";
 }
}
类NameReverseOrder

package com.jack.SortStrategy;

import java.util.Comparator;

public class NameReverseOrder implements Comparator<Person> {
 @Override
 public int compare(Person o1, Person o2) {
  // TODO Auto-generated method stub
  int result=o2.getName().compareTo(o1.getName());
  if(0==result){                                                              //若姓名相同按id排
   return o1.getId()-o2.getId();
  }
  return result;
 }
 public String getMethodName()
 {
  return "按姓名逆序";
 }
}
类Client

package com.jack.SortStrategy;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;

public class Client {

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  ArrayList<Person> personList = new ArrayList<Person>();
  personList.add(new Person(1, "zhangsan", 20));
  personList.add(new Person(2, "lisi", 21));
  personList.add(new Person(3, "wangwu", 25));
  personList.add(new Person(4, "zhaoliu", 26));
  personList.add(new Person(5, "chenqi", 28));
  personList.add(new Person(6, "dongba", 10));
  personList.add(new Person(7, "zhansan", 15));
  personList.add(new Person(8, "liujiu", 26));

  
  /*
   * 可通过这里new不同的Comparator的实现从而实现不同的排序策略
   * 分别有
   *  IdOrder:按Id正序
   *  IdReverseOrder:按Id逆序
   * NameOrder:按姓名正序
   * NameReverseOrder:按姓名逆序
   * AgeOrder:按年龄正序
   * AgeReverseOrder:按年龄逆序
   */
  Comparator<Person> comp = new IdOrder();                       

  Collections.sort(personList, comp);

  System.out.println(((IdOrder)comp).getMethodName()+"  排序后的序列是:");
  
  System.out.println("-----------------------");

  for (Iterator<Person> itor=personList.iterator();itor.hasNext();) {
   
   Person p=itor.next();
   System.out.println(p.getId() + "  " +p.getName()+ "  " + p.getAge());
  }

 }

}

执行Client可以得到排序的结果

时间: 2024-07-31 21:35:04

java中策略模式深入分析及示例的相关文章

iOS App设计模式开发中策略模式的实现示例_IOS

这次介绍一下策略模式(Strategy Pattern),相比之下是一种比较简单的模式.它也叫政策模式(Policy Pattern). 策略模式使用的就是面向对象的继承和多态机制,其他的没有什么玄机.策略模式适合使用在: 1. 多个类只有在算法或行为上稍有不同的场景. 2. 算法需要自由切换的场景. 3. 需要屏蔽算法规则的场景. 使用策略模式当然也有需要注意的地方,那么就是策略类不要太多,如果一个策略家族的具体策略数量超过4个,则需要考虑混合模式,解决策略类膨胀和对外暴露问题.在实际项目中,

详解C++设计模式编程中策略模式的优缺点及实现_C 语言

策略模式(Strategy):它定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换.策略模式让算法的变化不会影响到使用算法的客户.策略模式和 Template 模式要解决的问题是相同(类似)的,都是为了给业务逻辑(算法)具体实现和抽象接口之间的解耦.策略模式将逻辑(算法)封装到一个类(Context)里面,通过组合的方式将具体算法的实现在组合对象中实现,再通过委托的方式将抽象接口的实现委托给组合对象实现.State 模式也有类似的功能,他们之间的区别将在讨论中给出. UML图

Java设计模式--策略模式

策略模式(别名:政策) 定义一系列算法,把它们一个个封装起来,并且使它们可相互替换.本模式使得算法可独立于使用它的客户而变化. Strategy Pattern(Another Name: Policy) Define a family of algorithms, encapsulate each one, and make them inter changeable. Strategy lets the algorithm vary independently from clients th

Java中的模式

世上一直有一个神话:设计可以并且应该独立于实现的细节,设计通常被看作是一个抽象的概念而实现是一个代码的具体实例.如果我们坚信"设计是一个富有创造性和目的性的活动:为某一个目标而精心制定的结构的概念,",一个结构如果不能够说明它的环境,或者不能与环境协作,那么这个结构就不适合这一目标.环境中包括目标平台--语言.工具.库.中间件(middleware),等.还有它的功能性和非功能性的单元. 我们会认为在不知道地形布局的时候设计房屋,或者在不清楚使用的道材料的时候建造摩天大厦是不合理的事情

在java中使用dom4j解析xml(示例代码)_java

虽然Java中已经有了Dom和Sax这两种标准解析方式 但其操作起来并不轻松,对于我这么一个初学者来说,其中部分代码是活生生的恶心 为此,伟大的第三方开发组开发出了Jdom和Dom4j等工具 鉴于目前的趋势,我们这里来讲讲Dom4j的基本用法,不涉及递归等复杂操作 Dom4j的用法很多,官网上的示例有那么点儿晦涩,这里就不写了 首先我们需要出创建一个xml文档,然后才能对其解析 xml文档: 复制代码 代码如下: <?xml version="1.0" encoding=&quo

Java中的vector类使用示例小结_java

基本操作示例 VectorApp.java import java.util.Vector; import java.lang.*; import java.util.Enumeration; public class VectorApp { public static void main(String args[]) { Vector v1 = new Vector(); Integer integer1= new Integer(1); //加入为字符串对象 v1.addElement("o

精解Java中代理模式的实现

简介摘要: 代理模式是GOF设计模式中的一种,常用于权限模块的架构设计,其根本的原理是通过将一个代理对象交给调用者,使得调用者不能直接使用相应的功能模块,所 有的调用被传递给代理对象,代理对象负责对真实模块完成调用,在调用者与被调用者之间建立了一个隔离带,我们可以使 代理模式是GOF设计模式中的一种,常用于权限模块的架构设计,其根本的原理是通过将一个代理对象交给调用者,使得调用者不能直接使用相应的功能模块,所有的调用被传递给代理对象,代理对象负责对真实模块完成调用,在调用者与被调用者[bei t

[J2SE]Java中3DES加密解密调用示例_JSP编程

jce.jar security/US_export_policy.jar security/local_policy.jar ext/sunjce_provider.jar Java运行时会自动加载这些包,因此对于带main函数的应用程序不需要设置到CLASSPATH环境变量中.对于WEB应用,不需要把这些包加到WEB-INF/lib目录下. 以下是java中调用sun公司提供的3DES加密解密算法的样本代码: 复制代码 代码如下: /*字符串 DESede(3DES) 加密*/ import

java实现策略模式使用示例_java

思路如下: 使用interface来定义一个接口,在该接口中定义save()方法:根据图片格式定义不同的类,分别在这些类中使用关键字implements实现接口:创建一个实现选择的类,在该类中定义实现选择的方法,该方法返回值为对应的图片保存类:在主方法中实现接口.代码如下: 复制代码 代码如下: public interface ImageSaver {    void save();//定义save()方法} public class GIFSaver implements ImageSave