设计模式学习_策略模式

策略者模式 Strategy Pattern

使用背景

  • 定义: 我们将算法Algorithm与使用者Client分离,让这些使用者自由地选择策略。

想象这样一个场景:

有一个基类Duck,它具有两个方法:void eat() 与 void fly()

eat代表吃 fly代表飞行

现在有两个subclass 子类:WildDuck 与 CityDuck

  1. 它们在eat的行为上一摸一样

  2. 它们在fly的行为上不一样

试想,如果我们用Java来实现:

整个UML图可能是这样:

在这里插入图片描述

其中,- 代表这是一个私有方法,且void代表它无返回值。

前面,我们提到:这两种鸭子的eat行为是一样的,而fly的行为不一样。

那么,在这种单重继承的情况下,如果eat行为一样,我们只能重复的复制粘贴代码。

  • 想象一下,当子类的数目在需求增大的过程中越来越多?这样的代码不具有高重用性与可维护性。

使用策略者模式解决问题

  1. 在上述问题中,eat与fly可以代表两种算法或者策略

  2. 使用者就是WildDuck以及CityDuck

我们希望对于不同的使用者,可以任意使用策略。

解决方案:

我们将同一种策略,封装成接口Interface,然后采用不同的实现策略(即不同的实现类)

同时,将这些接口,注入到我们的使用者中。

使用具体的方法时,我们使用这些使用者的所注入进来的实现类的具体方法。

直接上UML图:(图不规范,见谅。)

在这里插入图片描述

从这个图中,我们可以看到:

  1. Duck类具有两个接口:IEatBehavior与IFlyBehavior

  2. 每个接口都有若干个实现类(策略)

  3. 当子类WildDuck与CityDuck继承Duck时,具有父类的所有资源。

  • 那么如何用代码实现呢?

代码实现:

  1. 首先,我们要有一个基类 Duck.java以及它的子类 WildDuck.java与CityDuck.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    package com.company.entity;

    import com.company.inter.IEatBehavior;
    import com.company.inter.IFlyBehavior;

    public class Duck {
    IEatBehavior iEatBehavior;

    IFlyBehavior iFlyBehavior;

    public Duck(IEatBehavior iEatBehavior, IFlyBehavior iFlyBehavior) {
    this.iEatBehavior = iEatBehavior;
    this.iFlyBehavior = iFlyBehavior;
    }

    public void eat(){
    this.iEatBehavior.eat();
    }

    public void fly(){
    this.iFlyBehavior.fly();
    }

    }

可以看到,这里有两个接口,分别代表两种策略(Eat与Fly)

# WildDuck.java

1
2
3
4
5
6
7
8
9
10
11
package com.company.entity;

import com.company.inter.IEatBehavior;
import com.company.inter.IFlyBehavior;

public class WildDuck extends Duck{
public WildDuck(IEatBehavior iEatBehavior, IFlyBehavior iFlyBehavior) {
super(iEatBehavior, iFlyBehavior);
}
}

# CityDuck.java

1
2
3
4
5
6
7
8
9
10
11
package com.company.entity;

import com.company.inter.IEatBehavior;
import com.company.inter.IFlyBehavior;

public class CityDuck extends Duck{
public CityDuck(IEatBehavior iEatBehavior, IFlyBehavior iFlyBehavior) {
super(iEatBehavior, iFlyBehavior);
}
}

  1. 定义两种接口

# iEatBehavior.java

1
2
3
4
5
6
package com.company.inter;

public interface IEatBehavior {
public void eat();
}

# iFlyBehavior.java

1
2
3
4
5
6
package com.company.inter;

public interface IFlyBehavior {
public void fly();
}

  1. 定义这些接口的不同策略实现类

# SimpleEatBehaviorImpl.java

1
2
3
4
5
6
7
8
9
10
package com.company.impl;

import com.company.inter.IEatBehavior;

public class SimpleEatBehaviorImpl implements IEatBehavior {
@Override
public void eat() {
System.out.println("吃:采用正常吃饭的策略!");
}
}

# SimpleFlyBehaviorImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.company.impl;

import com.company.inter.IFlyBehavior;

public class SimpleFlyBehaviorImpl implements IFlyBehavior {

@Override
public void fly() {
System.out.println("飞:采用正常飞的策略!");
}
}

# JetFlyBehaviorImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
package com.company.impl;

import com.company.inter.IFlyBehavior;

public class JetFlyBehaviorImpl implements IFlyBehavior {

@Override
public void fly() {
System.out.println("飞:采用喷气式飞行的策略!");
}
}

  • 那么目前为止,我们已经将这些策略与使用者分离了。

使用的时候,我们只需要让他们使用不同的策略即可。

# Main.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.company;

import com.company.entity.CityDuck;
import com.company.entity.WildDuck;
import com.company.impl.JetFlyBehaviorImpl;
import com.company.impl.SimpleEatBehaviorImpl;
import com.company.impl.SimpleFlyBehaviorImpl;
import com.company.inter.IEatBehavior;
import com.company.inter.IFlyBehavior;

public class Main {

public static void main(String[] args) {

//对于城市Duck来说 Eat采用的是simpleEat策略 Fly也采用的是simpleFly策略
IEatBehavior iSimpleEatBehavior = new SimpleEatBehaviorImpl();
IFlyBehavior iSimpleFlyBehavior = new SimpleFlyBehaviorImpl();
CityDuck cityDuck = new CityDuck(iSimpleEatBehavior, iSimpleFlyBehavior);
System.out.println("城市鸭子采用的策略:");
cityDuck.eat();
cityDuck.fly();

//对于城市Duck来说 Eat采用的是simpleEat策略(直接重用) Fly采用的是jetFly策略
IFlyBehavior iJetFlyBehavior = new JetFlyBehaviorImpl();
WildDuck wildDuck = new WildDuck(iSimpleEatBehavior, iJetFlyBehavior);
System.out.println("接下来是野鸭子采用的策略:");
wildDuck.eat();
wildDuck.fly();

}
}

效果图:

在这里插入图片描述