【策略模式-strategy】

article/2025/8/22 17:57:05

1:定义:

在《head first Design Pattern》中的定义是:策略模式定义了算法族,分别分装起来,让它们之间可以相互替换,此模式让算法的变化独立于使用算法的客户。

2:设计原则

1)   找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
2)   针对接口编程,而不是针对实现编程。
3)   多用组合,少用继承。
3策略模式的编写步骤

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

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

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

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

4,实际例子:
    head first <span lang="EN-US" style="" font-size:10.5pt;"="">Design Pattern》的例子(简化后):模拟一个鸭子游戏,游戏中有三种鸭子(绿头鸭MallardDuck, 红头鸭RedheadDuck
,橡皮鸭RubberDuck,诱饵鸭DecoyDuck),鸭子们都会游泳,外表各不相同,同类型鸭子叫声相同,绿头鸭和红头鸭会飞会叫,橡皮鸭不会飞但会叫,诱饵鸭不会飞不会叫,请设计这个游戏。
1,我们可能这么设计:

该设计的缺陷是:
绿头鸭和红头鸭叫声相同,但是quack()却无法复用,如果该行为要修改,那么修改该行为非常麻烦,你必须得往下追踪并在每一个定义此行为的类中修改它,这将是可怕的。
解决方法:分开变化的与不会变化的部分;体现(设计原则1
Duck类内的fly()quack()会随着鸭子的不同而改变,将这两个行为从Duck类中分开,形成算法族

整体类结构如下所示:

详细代码:
飞行的接口:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. interface FlyBehavior{  
  2.     public void fly();  
  3. }  
两个飞行类的实现:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class FlyWithwings implements FlyBehavior{  
  2.     public void fly(){  
  3.         System.out.println("can fly");  
  4.     }  
  5. }  
  6. class FlyNoWay implements FlyBehavior{  
  7.     public void fly(){  
  8.         System.out.println("can not fly");  
  9.     }  
  10. }  
叫声的接口:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. interface QuackBehavior{  
  2.     public void quack();  
  3. }  
三个叫声行为的实现:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class Quack implements QuackBehavior{  
  2.     public void quack(){  
  3.         System.out.println("guagua");  
  4.     }  
  5. }  
  6. class Squeak implements QuackBehavior{  
  7.     public void quack(){  
  8.         System.out.println("zhizhi");  
  9.     }  
  10. }  
  11. class MuteQuack implements QuackBehavior{  
  12.     public void quack(){  
  13.         System.out.println("can not fly");  
  14.     }  
  15. }  
鸭子的基类:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. abstract class Duck {  
  2.     FlyBehavior flyBehavior;  
  3.     QuackBehavior quackBehavior;  
  4.     public abstract void display();  
  5.     public void performFly(){  
  6.         flyBehavior.fly();  
  7.     }  
  8.     public void performQuack(){  
  9.         quackBehavior.quack();  
  10.     }  
  11.     public void swim(){  
  12.         System.out.println("All ducks can swim");  
  13.     }  
  14. }  
java Comparator使用的就是该设计模式,就是不改变对象本身,而是用一个策略对象改变它的行为;以下模拟下它的实现过程。
题目:人有年龄和身高两种属性,现在要对不同的人排序,可以按年龄也可以按身高。
人物类定义:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class perSon {  
  2.     int Age;  
  3.     int weigth;  
  4.   
  5.     perSon(int Age, int weigth) {  
  6.         this.Age = Age;  
  7.         this.weigth = weigth;  
  8.     }  
  9.     public void printinfo(){  
  10.         System.out.println("age:"+Age+"  weight:"+ weigth);  
  11.     }  
  12. }  
MyComparator接口:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. interface MyComparator<T> {  
  2.     public int compare(T o1, T o2);  
  3. }  
接下来是两种比较策略,继承了接口MyComparator
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class perSonSortWithweigth implements MyComparator<perSon> {  
  2.   
  3.     @Override  
  4.     public int compare(perSon o1, perSon o2) {  
  5.         // TODO Auto-generated method stub  
  6.         // TODO Auto-generated method stub  
  7.         if (o1.weigth > o2.weigth) {  
  8.             return 1;  
  9.         } else if (o1.weigth == o2.weigth) {  
  10.             return 0;  
  11.         } else {  
  12.             return -1;  
  13.         }  
  14.   
  15.     }  
  16. }  
  17.   
  18. class perSonSortWithAge implements MyComparator<perSon> {  
  19.   
  20.     @Override  
  21.     public int compare(perSon o1, perSon o2) {  
  22.         // TODO Auto-generated method stub  
  23.         if (o1.Age > o2.Age) {  
  24.             return 1;  
  25.         } else if (o1.Age == o2.Age) {  
  26.             return 0;  
  27.         } else {  
  28.             return -1;  
  29.         }  
  30.   
  31.     }  
  32. }  
接下来模拟arrays类(api中的arrays要复杂的多);
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class myArrays {  
  2.     public static <T> void sort(T[] arr, MyComparator<? super T> c) {  
  3.         T temp;  
  4.         // 简单的冒泡排序  
  5.         // 比较相邻的元素。如果第一个比第二个大,就交换他们两个。  
  6.         // 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。最后的元素应该会是最大的数。  
  7.         // 针对所有的元素重复以上的步骤,除了最后一个。  
  8.         for (int i = 0; i < arr.length - 1; i++) {  
  9.             for (int j = 0; j < arr.length - i - 1; j++) {  
  10.                 if (c.compare(arr[j + 1], arr[j]) >= 0) {  
  11.                     temp = arr[j];  
  12.                     arr[j] = arr[j + 1];  
  13.                     arr[j + 1] = temp;  
  14.                 }  
  15.             }  
  16.         }  
  17.     }  
  18. }  
测试如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class test {  
  2.     public static void main(String[] args) {  
  3.         perSon[] persons=new perSon[]{new perSon(1,2),new perSon(2,3),new perSon(3,0)};   
  4.         myArrays.sort(persons,new perSonSortWithAge());  
  5.         for(int i=0;i<persons.length;i++){  
  6.             persons[i].printinfo();  
  7.         }  
  8.         myArrays.sort(persons, new perSonSortWithweigth());  
  9.         for(int i=0;i<persons.length;i++){  
  10.             persons[i].printinfo();  
  11.         }  
  12.           
  13.     }  
  14. }  
既然提到了Comparator,那么顺便介绍下Comparable接口吧;对于上边的题目,如果用Comparable接口该这么实现:
MyComparable接口定义如下:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. interface MyComparable<T> {  
  2.     int compareTo(T o);  
  3. }  
人物类继承接口:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class person implements MyComparable {  
  2.     int Age;  
  3.     int weigth;  
  4.   
  5.     person(int Age, int weigth) {  
  6.         this.Age = Age;  
  7.         this.weigth = weigth;  
  8.     }  
  9.   
  10.     public void printinfo() {  
  11.         System.out.println("age:" + Age + "  weight:" + weigth);  
  12.     }  
  13.   
  14.     @Override  
  15.     public int compareTo(Object o) {  
  16.         // TODO Auto-generated method stub  
  17.         if(Age > ((person)o).Age){  
  18.             return 1;  
  19.         }else if(Age == ((person)o).Age){  
  20.             return 0;  
  21.         }else{  
  22.             return -1;  
  23.         }  
  24.     }  
  25. }  
arrays
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. class MyArrays{  
  2.     public static void sort(Object[] arr){  
  3.         Object temp;  
  4.         for (int i = 0; i < arr.length - 1; i++) {  
  5.             for (int j = 0; j < arr.length - i - 1; j++) {  
  6.                 if (((MyComparable)arr[j + 1]).compareTo(arr[j])  >= 0) {  
  7.                     temp = arr[j];  
  8.                     arr[j] = arr[j + 1];  
  9.                     arr[j + 1] = temp;  
  10.                 }  
  11.             }  
  12.         }  
  13.     }  
  14. }  
测试代码为:
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class test1 {  
  2.     public static void main(String[] args) {  
  3.         person[] persons=new person[]{new person(1,2),new person(2,3),new person(3,0)};   
  4.         MyArrays.sort(persons);  
  5.         for(int i=0;i<persons.length;i++){  
  6.             persons[i].printinfo();  
  7.         }  
  8.     }  
  9. }  
那么他们的区别如下所示:

Comparable 和 Comparator 都是用来实现集合中元素的比较、排序的。

只是 Comparable 是在集合内部定义的方法实现的排序,而Comparator 是在集合外部实现的排序,

所以,如想实现排序,就需要在集合外定义 Comparator 接口的方法或在集合内实现 Comparable 接口的方法。

Comparator位于包java.util下,而Comparable位于包 java.lang下

一.Comparable 是一个对象,本身就已经支持自比较所需要实现的接口(如 String、Integer 自己就可以完成比较大小操作,已经实现了Comparable接口)

自定义的类要在加入list容器中后能够排序,可以实现Comparable接口,在用Collections类的sort方法排序时,如果不指定Comparator,那么就以自然顺序排序,这里的自然顺序就是实现Comparable接口设定的排序方式。

二.Comparator 是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较。
可以说一个是自已完成比较,一个是外部程序实现比较的差别而已。


http://chatgpt.dhexx.cn/article/HMZD5jZq.shtml

相关文章

策略模式——Strategy

文章目录 案例展示——Strategy怎么用&#xff1f;深入分析——Strategy是什么&#xff1f;Strategy的定义Strategy的优点Strategy的缺点策略模式的扩展——策略枚举 参考 案例展示——Strategy怎么用&#xff1f; 了解一点历史的人都知道商鞅变法&#xff0c;正是由于商鞅变法…

策略模式,Strategy

策略模式的定义是&#xff1a; 定义一组算法&#xff0c;封装每个算法&#xff0c;让它们可以互换。让客户端可以单独切换算法。 其UML类图的示例如下&#xff1a; 在这个模式中&#xff0c;参与者包括&#xff1a; Strategy&#xff1a;为所有支持的算法声明一个共同的接口。…

策略模式/Strategy

策略模式/Strategy 意图/适用场景&#xff1a; 策略模式是针对一组算法&#xff0c;将每一个算法封装到具有共同接口的独立类中&#xff0c;从而使得它们可以互换。这样做的好处是&#xff0c;客户端可以以插件的方式更换算法。 电子商务网站的购物车系统是一个策略模式非常适用…

Strategy - 策略模式

定义 定义一系列的算法&#xff0c;把它们一个一个的封装起来&#xff0c;并且使它们可以相互替换&#xff0c;策略模式使得算法可以独立于使用者而变化。 案例 比如现在有一个文件编辑器Editor&#xff0c;它在保存的时候&#xff0c;可以保存为任意的格式。所有文件内容转换均…

策略模式 strategy

策略模式是对算法的包装&#xff0c;是把使用算法的责任和算法本身分割开来&#xff0c;委派给不同的对象管理。策略模式通常把一个系列的算法包装到一系列的策略类里面&#xff0c;作为一 个抽象策略类的子类。用一句话来说&#xff0c;就是&#xff1a;“准备一组算法&#x…

策略模式Strategy

策略模式是行为模式的一种&#xff0c;和模板模式解决的问题一样&#xff0c;实现了通用逻辑和算法细节的解耦合&#xff0c;不同的是模板模式采用继承实现&#xff0c;基类中通用逻辑需要确定下来不可随意更改&#xff0c;策略模式采用组合实现&#xff0c;比较灵活&#xff0…

Strategy策略

针对问题 针对特定问题具有多种算法时&#xff0c;我们需要根据上下文随时切换策略&#xff0c;这时运用strategy模式就能良好地组织代码关系&#xff0c;实现灵活选择和切换。 例子 1、诸葛亮的锦囊妙计&#xff0c;每一个锦囊就是一个策略。 2、旅行的出游方式&#xff0c…

策略(Strategy)模式

9. 策略(Strategy) Intent 定义一系列算法,封装每个算法,并使它们可以互换。 策略模式可以让算法独立于使用它的客户端。 Class Diagram Strategy 接口定义了一个算法族,它们都实现了 behavior() 方法。Context 是使用到该算法族的类,其中的 doSomething() 方法会调用…

策略模式使用

策略模式 策略模式就是定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换&#xff1b;它可以替换继承关系&#xff0c;避免使用多重条件转移语句 典型应用场景 根据不同的类型选择不同的计费策略、处理机制 参考&#xff1a;https://blog.csdn.net/u010247622/…

Option Explicit的作用

在VBScript中经常可以看到代码的最上面会出现“Option Explicit”&#xff0c;那么它的作用到底是干什么的呢&#xff1f; VBScript中并不要求显示定义变量&#xff0c;即变量可以不经定义直接使用&#xff0c;这样很方便&#xff0c;但是也很容易出现问题&#xff1b; 比如先定…

策略模式(常用用法)

策略模式 在软件开发中常常遇到类似的情况&#xff0c;当实现某一个功能存在多种算法或者策略&#xff0c;我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能&#xff0c;如数据排序策略有冒泡排序、选择排序、插入排序、二叉树排序等。 策略&#xff08;St…

策略模式之配置策略

了解策略模式建议大家先看一下这篇 https://www.runoob.com/design-pattern/strategy-pattern.html 步骤一创建一个接口 public interface Strategy {public int love(int a,int b); } 然后实现对应的接口A和B public class StrategyA implements Strategy {Overridepubli…

策略模式--strategy

策略模式 含义: 策略模式&#xff08;Strategy&#xff09;属于对象行为型设计模式&#xff0c; 1.主要是定义一系列的算法&#xff0c; 2.把这些算法一个个封装成拥有共同接口的单独的类&#xff0c;并且使它们之间可以互换。 策略模式使这些算法在客户端调用它们的时候能够互…

策略模式(Strategy)

设计模式系列 Strategy 策略模式——对象行为模式 1.意图 定义一系列的算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可相互替换。本模式使得算法可独立使用它的客户而变化。 2.适用性 当存在以下情况时使用Strategy模式 许多相关的类仅仅是行为有异。“策…

CTA 策略分享之三 -- 策略优化

上一个帖子介绍了一个趋势跟踪策略的优化思路&#xff0c;今天我们继续对策略进行分析&#xff0c;找到另外的优化方法。先看回测的权益曲线&#xff1a; 看到在2017 8月份到2018 2月份策略出现了较大的回撤。先定性分析一下&#xff0c;应该是在这段时间内日线级别的图形上震…

证书扩展中的oid

4.1.2.9. 扩展 该字段必须仅在版本为 3 时出现&#xff08;第 4.1.2.1 节&#xff09;。 如果存在&#xff0c;该字段是一个或多个证书扩展的序列。 Internet PKI 中证书扩展的格式和内容在第 4.2 节中定义。 为 X.509 v3 证书定义的扩展提供了将附加属性与用户或公钥相关联以及…

OID科普:物联网OID与互联网域名的区别 | 圣笛数控

1.主导机构不同&#xff0c;物联网OID是以全球共同参与的国际标准组织统一分配。各国管理自己境内部分&#xff0c;各国之间又可以互通。安全机制比互联网域名更高&#xff0c;既有高度自治又有全球互通。中国是整个体系中最大的支持者和应用者。 2.表现形式不同&#xff0c;物…

OID技术与物联网、区块链、大数据的关系 | OID科普

一、什么是物联网&#xff1f; 物联网既是网络与物品与企业与人与万物互联&#xff0c;更是信息技术业务和应用。是利用局部网络或互联网等通信技术把传感器、控制器、机器、人员和物等通过新的方式联在一起&#xff0c;形成人与物、物与物相联&#xff0c;实现信息化、远程管…

ArcGIS中ObjectID,FID和OID字段区别

ArcGIS中ObjectID&#xff0c;FID和OID字段区别 当我们创建一个Shapefiles&#xff08;shp&#xff09;, geodatabase feature classes&#xff08;gdb中的要素类&#xff09;或独立的dBase表&#xff08;dbf&#xff09;时&#xff0c;ArcGIS会自动为上述三种格式创建一个ID字…

圣笛数控|OID是什么?看OID在未来人类社会生活中的地位

OID定义&#xff0c;OID是什么&#xff1f; OID&#xff08;Object Identifier 对象标识符&#xff09;&#xff0c;是由国际三大标准组织ISO、IEC、ITU向全球颁布并供各国共同遵守的物品身份标识标准体系&#xff0c;现已被208个国家和地区采用。OID作为全球新物联通识标准&a…