让GTA 5来告诉你什么是策略模式(Strategy)

编程入门 行业动态 更新时间:2024-10-09 04:21:31

让GTA 5来<a href=https://www.elefans.com/category/jswz/34/1762275.html style=告诉你什么是策略模式(Strategy)"/>

让GTA 5来告诉你什么是策略模式(Strategy)

目录

 

了解策略模式

让GTA 5给你展示策略模式

咱们自己从代码上实现:

鼻子策略族

鼻子策略接口:

大鼻子——鼻子具体策略1

高鼻子——鼻子具体策略2

小鼻子——鼻子具体策略3

眉毛策略族

眉毛策略接口:

平直眉——眉毛具体策略1

上挑眉——眉毛具体策略2

一字眉——眉毛具体策略3

眼睛策略族

眼睛策略接口:

黑眼睛——眼睛具体策略1

蓝眼睛——眼睛具体策略2

紫眼睛——眼睛具体策略3

嘴策略族

嘴策略接口:

爱心唇——嘴具体策略1

覆舟唇——嘴具体策略2

厚嘴唇——嘴具体策略3

写角色:

角色父类:

策略角色1

策略角色2

测试——选择角色:

输出结果:

思考分析

1. 代码复用性高

2. 扩展性好


了解策略模式

策略模式(Strategy):它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到用算法的客户。

 

这句话怎么理解呢?

简单来讲,策略模式就是把“相似功能的算法”,或者叫做“功能相似的方法”,每个方法都独立出来写成个类。使用的时候,想用那个,就直接调用想相应的类方法就行。

 

然后这些相似功能的类,用一个接口去管理,这就叫算法家族了。

 

让GTA 5给你展示策略模式

玩过GTA 5线上模式的人应该都有捏脸的经历:

 

 

游戏截图,

鼻子+眼+眉毛+嘴  =》脸型

 

选择不同的鼻子、眉毛、眼、嘴,就是不同的策略,然后这些策略构成人物模型。

咱们自己从代码上实现:

鼻子、眉毛、眼、嘴,咱们每种选择3个类型(策略),来实现。

具体实现基本相同,看鼻子一个算法族的就够了。

以下开始写策略。

鼻子策略族

鼻子策略接口及其实现。

鼻子策略接口:

package 策略模式.鼻子;public interface 鼻子 {String 鼻子类型();
}

大鼻子——鼻子具体策略1

package 策略模式.鼻子;public class 大鼻子 implements 鼻子 {@Overridepublic String 鼻子类型() {return "大鼻子";}
}

高鼻子——鼻子具体策略2

package 策略模式.鼻子;public class 高鼻子 implements 鼻子 {@Overridepublic String 鼻子类型() {return "高鼻子";}
}

小鼻子——鼻子具体策略3

package 策略模式.鼻子;public class 小鼻子 implements 鼻子 {@Overridepublic String 鼻子类型() {return "小鼻子";}
}

眉毛策略族

眉毛策略接口及其实现。

眉毛策略接口:

package 策略模式.眉毛;public interface 眉毛 {String 眉毛类型();
}

平直眉——眉毛具体策略1

package 策略模式.眉毛;public class 平直眉 implements 眉毛 {@Overridepublic String 眉毛类型() {return "平直眉";}}

上挑眉——眉毛具体策略2

package 策略模式.眉毛;public class 上挑眉 implements 眉毛 {@Overridepublic String 眉毛类型() {// TODO 自动生成的方法存根return "上挑眉";}}

一字眉——眉毛具体策略3

package 策略模式.眉毛;public class 一字眉 implements 眉毛 {@Overridepublic String 眉毛类型() {// TODO 自动生成的方法存根return "一字眉";}}

眼睛策略族

眼睛策略接口及其实现。

眼睛策略接口:

package 策略模式.眼睛;public interface 眼睛 {String 眼睛类型();
}

黑眼睛——眼睛具体策略1

package 策略模式.眼睛;public class 黑眼睛 implements 眼睛 {@Overridepublic String 眼睛类型() {// TODO 自动生成的方法存根return "黑眼睛";}}

蓝眼睛——眼睛具体策略2

package 策略模式.眼睛;public class 蓝眼睛 implements 眼睛 {@Overridepublic String 眼睛类型() {// TODO 自动生成的方法存根return "蓝眼睛";}}

紫眼睛——眼睛具体策略3

package 策略模式.眼睛;public class 紫眼睛 implements 眼睛 {@Overridepublic String 眼睛类型() {// TODO 自动生成的方法存根return "棕眼睛";}}

嘴策略族

嘴策略接口及其实现。

嘴策略接口:

package 策略模式.嘴;public interface 嘴 {String 嘴型();
}

爱心唇——嘴具体策略1

package 策略模式.嘴;public class 爱心唇 implements 嘴 {@Overridepublic String 嘴型() {// TODO 自动生成的方法存根return "爱心唇";}}

覆舟唇——嘴具体策略2

package 策略模式.嘴;public class 覆舟唇 implements 嘴 {@Overridepublic String 嘴型() {// TODO 自动生成的方法存根return "覆舟唇";}}

厚嘴唇——嘴具体策略3


package 策略模式.嘴;public class 厚嘴唇 implements 嘴 {@Overridepublic String 嘴型() {// TODO 自动生成的方法存根return "厚嘴唇";}}

写角色:

以上已经制定好各种策略,从这里就开始展示怎么使用各种策略了。

角色父类:

package 策略模式.角色;import 策略模式.嘴.嘴;
import 策略模式.眉毛.眉毛;
import 策略模式.眼睛.眼睛;
import 策略模式.鼻子.鼻子;public abstract class 策略角色 {鼻子 bz;眉毛 mm;眼睛 yj;嘴 z;public 策略角色() {}public String 鼻子类型() {return bz.鼻子类型();}public String 眉毛类型() {return mm.眉毛类型();}public String 眼睛类型() {return yj.眼睛类型();}public String 嘴类型() {return z.嘴型();}
}

策略角色1

package 策略模式.角色;import 策略模式.嘴.爱心唇;
import 策略模式.眉毛.平直眉;
import 策略模式.眼睛.黑眼睛;
import 策略模式.鼻子.大鼻子;public class 策略角色1 extends 策略角色{public 策略角色1() {bz = new 大鼻子();mm = new 平直眉();yj = new 黑眼睛();z = new 爱心唇();}
}

策略角色2

package 策略模式.角色;import 策略模式.嘴.爱心唇;
import 策略模式.眉毛.平直眉;
import 策略模式.眼睛.黑眼睛;
import 策略模式.鼻子.高鼻子;public class 策略角色2 extends 策略角色{public 策略角色2() {bz = new 高鼻子();mm = new 平直眉();yj = new 黑眼睛();z = new 爱心唇();}
}

以上已经使用策略写了两个角色,接下来咱们进行测试使用。

测试——选择角色:

package 策略模式;import 策略模式.角色.策略角色1;
import 策略模式.角色.策略角色2;
import 策略模式.角色.非策略角色1;
import 策略模式.角色.非策略角色2;public class 选择角色 {public static void main(String[] args) {System.out.println("========");System.out.println("策略选择");System.out.println("========");策略角色1 one = new 策略角色1();System.out.println(one.鼻子类型()+"\n"+one.眉毛类型()+"\n"+one.眼睛类型()+"\n"+one.嘴类型());System.out.println("--------");策略角色2 two = new 策略角色2();System.out.println(two.鼻子类型()+"\n"+two.眉毛类型()+"\n"+two.眼睛类型()+"\n"+two.嘴类型());}
}

输出结果:

========
策略选择
========
大鼻子
平直眉
黑眼睛
爱心唇
--------
高鼻子
平直眉
黑眼睛
爱心唇

思考分析

为什么要用策略模式,都是一个角色一个类,为什么不直接写,反而把方法都写成一个类,还写接口,变得那么复杂?

 

1. 代码复用性高

其实这个很好理解。

 

我们想一下,为什么java要封装方法?直接在main方法里边写下去不久行了?

这个问题,相信很多人都已经有一定的理解了——为了提高代码的复用性,把常用的代码封装成方法,下次使用不用再写,直接调用就行。

 

来个小案例,加深一下理解。

假设我们有个需求:我们要分别对5个大小为5的数组进行比较,然后分别输出每个数组的最大值。

不封装成方法时,我们的代码是这样的:

package 策略模式.为什么封装方法;public class 方法封装 {Integer[] a = {5,9,7,6,1};Integer[] b = {6,8,5,3,4};Integer[] c = {0,4,6,2,7};Integer[] d = {8,4,9,2,5};Integer[] e = {1,6,2,0,5};public 方法封装() {sort();}private void sort() {int j=0;// 对a进行排序for (int i = 0; i < a.length-1; i++) {if(a[i]>a[i+1]) {j=a[i+1];a[i+1]=a[i];a[i]=j;}}System.out.println(a[4]);// 对b进行排序for (int i = 0; i < b.length-1; i++) {if(b[i]>b[i+1]) {j=b[i+1];b[i+1]=b[i];b[i]=j;}}System.out.println(b[4]);// 对c进行排序for (int i = 0; i < c.length-1; i++) {if(c[i]>c[i+1]) {j=c[i+1];c[i+1]=c[i];c[i]=j;}}System.out.println(c[4]);// 对d进行排序for (int i = 0; i < d.length-1; i++) {if(d[i]>d[i+1]) {j=d[i+1];d[i+1]=d[i];d[i]=j;}}System.out.println(d[4]);// 对e进行排序for (int i = 0; i < e.length-1; i++) {if(e[i]>e[i+1]) {j=e[i+1];e[i+1]=e[i];e[i]=j;}}System.out.println(e[4]);}public static void main(String[] args) {new 方法封装();}}

很明显,赤裸裸的粘贴复制了4次!

封装一下,代码是这样的:
 

package 策略模式.为什么封装方法;public class 方法封装 {Integer[] a = {5,9,7,6,1};Integer[] b = {6,8,5,3,4};Integer[] c = {0,4,6,2,7};Integer[] d = {8,4,9,2,5};Integer[] e = {1,6,2,0,5};public 方法封装() {sort(a);sort(b);sort(c);sort(d);sort(e);}private void sort(Integer[] a) {int j=0;// 对a进行排序for (int i = 0; i < a.length-1; i++) {if(a[i]>a[i+1]) {j=a[i+1];a[i+1]=a[i];a[i]=j;}}System.out.println(a[4]);}public static void main(String[] args) {new 方法封装();}}

现在直观的明白封装方法的好处了吧?

 

对应到类之间,如果类做的事都是同一件事。那代码重复率岂不是跟上边不使用方法那样?

咱们来做一个不使用策略模式创建角色和使用策略对比下。

不使用策略:

非策略角色父类

package 策略模式.角色;public abstract class 非策略角色 {public String 鼻子类型() {return "";}public String 眉毛类型() {return "";}public String 眼睛类型() {return "";}public String 嘴类型() {return "";}
}

非策略角色1

package 策略模式.角色;public class 非策略角色1 extends 非策略角色{@Overridepublic String 鼻子类型() {return "大鼻子";}@Overridepublic String 眉毛类型() {return "平直眉";}@Overridepublic String 眼睛类型() {return "黑眼睛";}@Overridepublic String 嘴类型() {return "爱心唇";}
}

非策略角色2

package 策略模式.角色;public class 非策略角色2 extends 非策略角色{@Overridepublic String 鼻子类型() {return "高鼻子";}@Overridepublic String 眉毛类型() {return "平直眉";}@Overridepublic String 眼睛类型() {return "黑眼睛";}@Overridepublic String 嘴类型() {return "爱心唇";}
}

看看,不使用策略模式,就只能复写父类的方法。哪怕只改动了鼻子类型,其他的也都需要复写。

 

我们只使用了4个部位,3中选择的小案例。

假如我们要把所有的可能都写出来。

那么,策略模式需要写:4*3=12个方法+3*3*3*3=81次调用。

非策略需要写:4个父类方法+3*3*3*3=81个子类复写方法。

 

 

相信大家已经很明确的知道了,策略模式,代码复用性好的优点。

 

 

2. 扩展性好

现在有个需求,角色3需要“柳叶眉”

我们需要怎么做?

再写个实现眉毛接口的实现类就行了!

package 策略模式.眉毛;public class 柳叶眉 implements 眉毛 {@Overridepublic String 眉毛类型() {return "柳叶眉";}}

然后,新建角色时,就可以直接选择了:

策略角色3

package 策略模式.角色;import 策略模式.嘴.爱心唇;
import 策略模式.眉毛.柳叶眉;
import 策略模式.眼睛.黑眼睛;
import 策略模式.鼻子.高鼻子;public class 策略角色3 extends 策略角色{public 策略角色3() {bz = new 高鼻子();mm = new 柳叶眉();yj = new 黑眼睛();z = new 爱心唇();}
}

 

缺点

谈完优点,再来说缺点:

其实,他的优点也是缺点。

当策略很多时,我们要写的实现类太多了。

而且,因为策略都要提供被选择,所以所有的策略都是public——暴露的!

 

 

个人所学和总结,如果那里不对,希望看到的大佬指正批评!

更多推荐

让GTA 5来告诉你什么是策略模式(Strategy)

本文发布于:2024-03-14 15:37:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1736786.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:告诉你   策略   模式   GTA   Strategy

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!