软件开发中功能实现算法策略选择:硬编码带来的问题与思考

1.背景

软件开发中功能实现算法策略选择:硬编码带来的问题与思考

在软件开发过程中时常会碰到这样的情形,对于实现某一个特定功能,存在着多种不同的算法或者策略。我们能够依据所处的环境以及所具备的条件的差异,去挑选出不同的算法或者策略,从而达成该功能。查找和排序等操作,一种常见的方式是在一个类中进行硬编码。若需要提供多种查找算法,可把这些算法写在一个类里,在该类中设置多个方法,每个方法对应一个具体的查找算法。当然,也能将这些查找算法封装在一个统一的方法中,通过 if…else…或者 case 等条件判断语句来进行选择。

这两种实现方法都可称作硬编码。若要增添一种新的查找算法,就得修改封装算法类的源代码;若要更换查找算法,同样需要修改客户端调用代码。此算法类中封装了诸多查找算法,这类代码会比较复杂,维护起来较为困难。如果把这些策略包含在客户端,这种做法不可取。因为这会使客户端程序变得庞大且难以维护。尤其是当存在大量可供选择的算法时,问题会更加严重。

2.问题

如何让算法与对象相分离呢?这样就能使算法能够独立于使用它的客户而发生变化。

3.方案

将一个类中时常发生改变或者未来有可能改变的部分提取出来,使其成为一个接口。接着在该类中包含这个对象的实例。如此一来,类的实例在运行过程中就能够随意地调用实现了这个接口的类所具备的行为。

定义一系列的算法,将每一个算法进行封装,同时让它们能够相互替换,这样就能使算法独立于使用它的客户而发生变化,这便是策略模式。

4.适用情况

许多相关的类只是在行为方面有所不同。“策略”给出了一种方式,能够用多个行为中的某一个行为去对一个类进行配置。也就是说,一个系统需要在几种算法中动态地挑选出一种。

当一个应用程序需要达成一种特定的服务或者具备某种功能时,并且该程序存在多种实现的途径,就可以使用这种方式。

一个类定义了多种行为,这些行为在该类的操作中是以多个条件语句的形式呈现的。把相关的条件分支移到它们各自的 Strategy 类里面,以此来替代这些条件语句。

5.优点

1、可以动态的改变对象的行为

缺点

1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类

2、如果策略很多的话策略模式将造成产生很多策略类

6.例子

一款游戏能够制作出鸭子,这些鸭子都具备游泳的能力。然而,其中有的鸭子会飞,而有的鸭子则不会飞。并且,每只鸭子的外观也各不相同。在设计时,需要考虑到后期的扩展,例如后期鸭子吃了一个道具后,就可以增加火箭推动力从而能够飞行。

使用策略模式

策略模式注重用多个行为中的某一个行为来对一个类的方法进行配置。一个系统需要在几种算法中动态地选择一种。这意味着要将策略方法抽取出来。

为fly飞行方法写一个策略接口


/**
 * 控制飞行的接口
 */
public interface FlyBehavior {
    public abstract void fly();
}

写上应有的策略

**
 * 会飞行鸭子动作
 */
public class FlyWithWings implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("我是会飞行的鸭子");
    }
}

/**
 * 会用火箭推动器飞行的鸭子
 */
public class FlyWithRocket implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("我是可以使用火箭推动器飞行的鸭子");
    }
}


/**
 * 不会飞的鸭子
 */
public class FlyNoway implements FlyBehavior {
    @Override
    public void fly() {
        System.out.println("我是不会飞的鸭子");
    }
}

此策略已实现完毕。当下鸭子飞行存在三种策略,其一为会飞,其二为会借助火箭推送器飞行,其三为不会飞。若还有其他策略,皆可便捷地添加进来,进而提升了扩展性。

接着对鸭子的基类进行修改,具体情况如下:鸭子的各种行为都被委托给了 flyBehavior 这个专门用于鸭子的行为类。通过 Set 方法能够实现对鸭子行为的动态改变。

/**
 * 所有鸭子的基类
 */
public abstract class Duck {
    public FlyBehavior flyBehavior;//被委托的类
    //外观颜色
    public abstract void display();
    /**
     * 把行为委托给具体的行为类
     */
    public void preformFly(){
        flyBehavior.fly();
    }
      /**
     * 用于动态改变委托具体对象
     */
    public void setFlyBehavior(FlyBehavior flyBehavior) {
        this.flyBehavior = flyBehavior;
    }
}

测试的方法:

/**
 * 该鸭子为绿色,不会飞
 */
public class GreenDuck extends Duck {
    public static void main(String[] args) {
        //实例化对象
        GreenDuck greenDuck = new GreenDuck();
        //展示颜色
        greenDuck.display();
        //展示默认行为
        greenDuck.preformFly();
        System.out.println("吃了一个火箭推动器");
        //动态改变行为
        greenDuck.setFlyBehavior(new FlyWithRocket());
        greenDuck.preformFly();
    }
    public GreenDuck() {
        flyBehavior = new FlyNoway();//初始化默认行为
    }
    @Override
    public void display() {
        System.out.println("绿色鸭子");
    }
}

控制台输出:

分析

绿色鸭子自身原本是不会飞的。当它吃了道具之后,就能够飞起来了。这里需要对鸭子本身的飞行能力进行改变,也就是要动态地改变它的行为。这便是策略模式所带来的优点。

总之,策略模式将行为的实现都托付给接口去完成。它自身只需负责具体的行为策略。至于具体的调用方式以及调用哪个策略,是由客户端来决定并进行动态改变的。

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

25阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读