设计模式-策略
来源:互联网 发布:找网络推手联系方式 编辑:程序博客网 时间:2024/04/28 17:10
写在前面
正在学习23种设计模式,打算把自己的理解总结起来,以此加深学习效果。这些总结会引用学习的书籍和网上的文献,加上自己的理解。文章的结构基本为:是什么,为什么,怎么做,因为如果理清了这三个问题,就理解的差不多了。
什么是策略模式
策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
举个例子:我们的Duck
类中有一个飞行行为,而在使用了策略模式之后,我们就不打算把fly()
写在Duck
类中了,而是把fly()
方法封装到另一个FlyBehavior
类中,使其独立于Duck
类,而在使用的时候我们可以在Duck
类中加一个performFly()
方法,在这个方法里调用封装在FlyBehavior
类的fly()
方法,这样一旦我们对这个方法进行更改时,Duck
的飞行行为也会变化,那么什么是相互替换呢?我们知道飞行行为可以有多种方式,让FlyBehavior
成为接口,再加上几个其实现类,我们在调用时就可以动态决定使用哪种飞行方式,从而达到让让这些fly()
算法能够相互替换。
解释概念可能有点抽象,下面通过具体例子阐述。
为什么要用策略模式
让我们设想一个场景:还是前面的鸭子Duck
类,这个类会有一些基本属性,如鸭子的名称,还会有一些方法,如eat()
。现在有各种鸭子,如家鸭,野鸭,天鹅等等。我们让其继承父类Duck
,这样它就拥有基本属性和行为。现在有个需求:我们需要为其添加一个飞行行为,于是我们在父类Duck
中添加fly()
方法,这样所有鸭子都具有飞行行为了。
但是我们知道有的家鸭是不能飞的,于是我们想到行为应该用接口定义,让有飞行行为的鸭去实现这个接口,但是这么做又有了新问题,我们的代码复用性很差,不管fly()
方法是否一样,每个鸭子子类都要写一遍fly()
方法。
怎么用策略模式
策略模式就能解决这个问题。针对鸭的飞行行为,我们提炼出一个FlyBehavior
接口,接口中有fly()
方法,而让不同飞行方式,如FlywithWings
,FlyNoWay
去实现这个接口。即便我们有一百种鸭的子类,但是其飞行方式可能只有几种,这样就达到了代码的复用性。但是目前这几个飞行行为类并没有和Duck
子类产生任何联系,于是我们在父类Duck
中声明一个FlyBehavior
接口类型的变量:FlyBehavior flyBehavior;
,然后定义一个performFly()
方法,方法里调用变量flyBehavior
的fly()
方法。这样子类只要是调用performFly()
方法,就相当于调用我们之前抽出的fly()
方法。到目前为止,我们实现了让Duck
的任何子类不用编写任何飞行行为代码就能实现飞行,实现了代码复用性,而即便不能飞行的子类也有FlyNoWay
提供给它。
但是等等,我们还只是调用接口FlyBehavior
的fly()
方法,没有指定具体实现类,还不能做到我想使用哪个飞行方式就使用哪个。于是我们在鸭子的子类如野鸭WildDuck
类的构造方法中加上: flyBehavior = new FlywithWings();
,这样就指定了其飞行方式为用翅膀飞行,同样的,在其他鸭子的子类构造方法中指定具体的飞行方式,即为flyBehavior
变量实例化具体的FlyBehavior
接口实现类。
这样之后,如果某种飞行方式需要更改,我们只需要对飞行行为实现类的fly()
方法进行更改,就能让所有拥有该飞行方式的鸭子都更改生效。如果需要一种新的飞行方式,如机器鸭用机器进行飞行。我们只需定义一个FlyWithMachine
类让其实现FlyBehavior
接口的fly()
方法。然后机器鸭MachineDuck
的构造方法中指定:flyBehavior = new FlyWithMachine();
。而如果想在运行时动态更换鸭子飞行方式,我们可以在Duck
类中加一个set方法:
public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; }
从而达到动态调用setFlyBehavior
方法更换飞行方式。
示例代码
//飞行行为接口public interface FlyBehavior { public void fly();}//用翅膀的飞行方式public class FlyWithWings implements FlyBehavior{ @Override public void fly() { System.out.println("i am flying with wings"); }}//不会飞的飞行方式public class FlyNoWay implements FlyBehavior{ @Override public void fly() { // i can't fly,so i don't do anything... }}//用机器的飞行方式public class FlyWithMachine implements FlyBehavior{ @Override public void fly() { System.out.println("i am flying with machine"); }}//鸭子父类public abstract class Duck { protected String name; protected FlyBehavior flyBehavior; protected void eat(){ System.out.println("i am eating"); } public void performFly(){ flyBehavior.fly(); } public void setFlyBehavior(FlyBehavior flyBehavior) { this.flyBehavior = flyBehavior; } }//家鸭public class HomeDuck extends Duck{ public HomeDuck(){ flyBehavior = new FlyNoWay(); }}//野鸭public class WildDuck extends Duck{ public WildDuck(){ flyBehavior = new FlyWithWings(); }}public class Main { public static void main(String[] args) { System.out.println("homeDuck尝试飞行:"); Duck homeDuck = new HomeDuck(); homeDuck.performFly(); System.out.println("wildDuck尝试飞行:"); Duck wildDuck = new WildDuck(); wildDuck.performFly(); System.out.println("wildDuck改用机器飞行:"); wildDuck.setFlyBehavior(new FlyWithMachine()); wildDuck.performFly(); }}
打印:
homeDuck尝试飞行:
wildDuck尝试飞行:
i am flying with wings
wildDuck改用机器飞行:
i am flying with machine
- 设计模式-策略模式
- 设计模式:策略模式
- 设计模式-策略模式
- 设计模式 - 策略模式
- 设计模式-策略模式
- 设计模式-----策略模式
- 设计模式 策略模式
- 设计模式-策略模式
- 设计模式-【策略模式】
- 设计模式-----策略模式
- 设计模式-策略模式
- 设计模式--策略模式
- 设计模式- 策略模式
- 设计模式- 策略模式
- 设计模式------策略模式
- 设计模式--策略模式
- 设计模式-策略模式
- 设计模式--策略模式
- Jquery动画效果
- fsds
- 关于数据表多对多关联的理解
- iOS开发之网络编程篇一:网络开发基本概念介绍
- ie11浏览器访问javaWeb页面 提示 Audio未定义
- 设计模式-策略
- hello
- [JAVA]String与InputStream互转-20160412
- Elasticsearch Restore失灵
- codevs 1047 邮票面值设计
- 国际版firefox安装方法
- [LeetCode]31. Next Permutation
- Android中Bitmap,byte[],Drawable相互转化
- 我的创业经历