小谈设计模式(3)---策略模式
- 专栏介绍
- 策略模式
-
- 主要角色
-
- 环境(Context)
- 抽象策略(Strategy)
- [具体策略(Concrete Strategy)](#具体策略(Concrete Strategy))
- 角色总结
- 核心思想
- Java代码实现------以一个游戏角色攻击方式的例子
-
- [首先,我们定义一个抽象策略类 AttackStrategy,它声明了一个 attack() 方法:](#首先,我们定义一个抽象策略类 AttackStrategy,它声明了一个 attack() 方法:)
- [然后,我们定义两种具体的攻击策略类:MeleeAttackStrategy 和 RangedAttackStrategy,它们分别实现了 AttackStrategy 接口:](#然后,我们定义两种具体的攻击策略类:MeleeAttackStrategy 和 RangedAttackStrategy,它们分别实现了 AttackStrategy 接口:)
- [接下来,我们定义一个环境类 Character,它持有一个 AttackStrategy 对象,并提供一个 setAttackStrategy() 方法用于动态设置攻击策略:](#接下来,我们定义一个环境类 Character,它持有一个 AttackStrategy 对象,并提供一个 setAttackStrategy() 方法用于动态设置攻击策略:)
- 最后,我们可以在客户端中使用策略模式:
- 代码分析
- 优缺点分析
专栏介绍
专栏地址
专栏介绍
主要对目前市面上常见的23种设计模式进行逐一分析和总结,希望有兴趣的小伙伴们可以看一下,会持续更新的。希望各位可以监督我,我们一起学习进步,加油,各位。
策略模式
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列的算法,将每个算法封装起来,使它们可以互相替换。策略模式让算法的变化独立于使用算法的客户端。
主要角色
当我们使用策略模式时,通常会涉及三个主要角色:环境(Context)、抽象策略(Strategy)和具体策略(Concrete Strategy)。
环境(Context)
环境类是策略模式的核心,它持有一个策略对象的引用,并在运行时根据具体需求调用策略对象的算法。环境类提供了一个接口或方法,用于设置和获取策略对象。在客户端使用策略模式时,通常需要与环境类进行交互。
抽象策略(Strategy)
抽象策略类是策略模式的接口或抽象类,定义了具体策略类所必须实现的算法。抽象策略类通常包含一个或多个抽象方法,用于描述策略的行为。客户端通过调用抽象策略类中的方法来使用具体策略。
具体策略(Concrete Strategy)
具体策略类是策略模式的实现类,实现了抽象策略类中定义的算法。具体策略类根据具体的业务需求,实现了不同的算法逻辑。在客户端使用策略模式时,可以根据需要选择合适的具体策略类。
角色总结
环境类持有一个策略对象的引用,并在运行时根据具体需求调用策略对象的算法。抽象策略类定义了具体策略类所必须实现的算法,而具体策略类实现了具体的算法逻辑。通过使用策略模式,可以将算法的定义和使用分离,提高代码的灵活性、可维护性和可扩展性。
核心思想
策略模式的核心思想是将算法的定义和使用分离。在策略模式中,我们将不同的算法封装成不同的策略类,并通过环境类持有一个策略对象的引用。在运行时,根据具体需求选择合适的策略对象,并调用其算法。
封装算法
策略模式将不同的算法封装成不同的策略类。每个策略类都实现了一种具体的算法逻辑。通过封装算法,我们可以将其与其他代码分离,使得算法的定义更加清晰、可读、可维护。
定义抽象策略
策略模式定义了一个抽象策略类,其中包含了策略类所必须实现的方法。抽象策略类可以是一个接口或者抽象类。通过定义抽象策略,我们可以统一不同策略类的接口,使得客户端可以以统一的方式使用不同的策略。
使用环境类
策略模式通过环境类持有一个策略对象的引用。在运行时,客户端可以根据具体需求选择合适的策略对象,并将其设置到环境类中。环境类在运行时根据具体需求调用策略对象的算法,实现了算法的动态切换。
思想总结
通过将算法的定义和使用分离,策略模式提高了代码的灵活性、可维护性和可扩展性。它使得算法的修改和增加变得更加简单,不需要修改原有的代码。同时,策略模式也符合开闭原则,可以方便地增加新的策略类。
Java代码实现------以一个游戏角色攻击方式的例子
首先,我们定义一个抽象策略类 AttackStrategy,它声明了一个 attack() 方法:
java
public interface AttackStrategy {
void attack();
}
然后,我们定义两种具体的攻击策略类:MeleeAttackStrategy 和 RangedAttackStrategy,它们分别实现了 AttackStrategy 接口:
java
public class MeleeAttackStrategy implements AttackStrategy {
@Override
public void attack() {
System.out.println("近战攻击");
}
}
public class RangedAttackStrategy implements AttackStrategy {
@Override
public void attack() {
System.out.println("远程攻击");
}
}
接下来,我们定义一个环境类 Character,它持有一个 AttackStrategy 对象,并提供一个 setAttackStrategy() 方法用于动态设置攻击策略:
JAVA
public class Character {
private AttackStrategy attackStrategy;
public void setAttackStrategy(AttackStrategy attackStrategy) {
this.attackStrategy = attackStrategy;
}
public void attack() {
attackStrategy.attack();
}
}
最后,我们可以在客户端中使用策略模式:
JAVA
public class Client {
public static void main(String[] args) {
Character character = new Character();
character.setAttackStrategy(new MeleeAttackStrategy());
character.attack(); // 输出:近战攻击
character.setAttackStrategy(new RangedAttackStrategy());
character.attack(); // 输出:远程攻击
}
}
代码分析
在上述代码中,我们通过设置不同的攻击策略,使得角色可以使用不同的攻击方式。这样,当需要增加新的攻击方式时,只需要实现新的具体策略类,并在客户端中设置新的攻击策略即可,而不需要修改原有的代码。
优缺点分析
优点
算法的封装性
策略模式将不同的算法封装成不同的策略类,使得每个策略类都只关注自己的算法逻辑,提高了代码的可读性和可维护性。
策略的替换性
由于策略模式将算法的定义和使用分离,所以在运行时可以根据具体需求选择不同的策略对象,实现算法的动态切换。这样可以方便地替换和扩展算法,而不需要修改原有的代码。
算法的扩展性
策略模式符合开闭原则,可以方便地增加新的策略类。当需要增加新的算法时,只需要添加一个新的策略类,并在环境类中设置该策略对象即可,不需要修改原有的代码。
算法的复用性
策略模式将算法封装成独立的策略类,可以在不同的场景中复用相同的算法。这样可以避免代码的重复编写,提高了代码的复用性。
缺点
增加了类的数量
使用策略模式会增加类的数量,每个具体策略类都需要单独定义一个类。如果策略较多,可能会导致类的数量过多,增加代码的复杂性。
客户端需要了解不同的策略类
客户端在使用策略模式时,需要了解不同的策略类,并选择合适的策略对象。如果策略较多,可能会增加客户端的复杂性。
策略的选择逻辑
在使用策略模式时,需要根据具体需求选择合适的策略对象。这个选择逻辑可能会比较复杂,需要考虑多个因素,增加了代码的复杂性。
优缺点总结
总的来说,策略模式通过将算法的定义和使用分离,提高了代码的灵活性、可维护性和可扩展性。它将不同的算法封装成不同的策略类,实现了算法的动态切换和复用。然而,策略模式也会增加类的数量,增加客户端的复杂性,并且需要考虑策略的选择逻辑。在使用策略模式时,需要权衡其优点和缺点,选择合适的使用方式。