返回

剑走偏锋:《设计模式之美》里的策略模式真相,远非简化分支判断!

Android

提起策略模式,许多程序员的第一反应就是"啊!原来设计模式还可以用来减少if-else或者switch的冗长判断,代码变得可读了,我也能变得帅了!"。然而,策略模式的价值远非如此,它是一种应对变化的通用解决方案,通过将算法或策略的实现与使用它们的环境分离,可以提高代码的可复用性和灵活性。

在《设计模式之美》一书中,作者用一个有趣的例子来介绍策略模式——一个图形绘制应用程序需要支持多种绘图形状,如圆形、矩形、三角形等。如果采用传统的if-else或者switch来判断绘图形状,那么代码将会变得冗长而难以维护。此时,策略模式就派上用场了。

// 定义一个绘图形状接口
interface Shape {
    void draw();
}

// 定义一个绘图器类,负责调用不同的绘图形状接口的draw()方法
class Drawer {
    private Shape shape;

    public void setShape(Shape shape) {
        this.shape = shape;
    }

    public void drawShape() {
        shape.draw();
    }
}

// 定义具体的绘图形状类,如圆形、矩形、三角形等
class Circle implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制圆形");
    }
}

class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制矩形");
    }
}

class Triangle implements Shape {
    @Override
    public void draw() {
        System.out.println("绘制三角形");
    }
}

// 使用绘图器类来绘制不同的绘图形状
Drawer drawer = new Drawer();
drawer.setShape(new Circle());
drawer.drawShape(); // 输出:绘制圆形

drawer.setShape(new Rectangle());
drawer.drawShape(); // 输出:绘制矩形

drawer.setShape(new Triangle());
drawer.drawShape(); // 输出:绘制三角形

通过这种方式,我们可以将绘图形状的具体实现与绘图器类解耦,使得绘图器类可以独立于绘图形状的具体实现进行工作。如果我们需要增加新的绘图形状,只需实现一个新的Shape接口即可,而无需修改绘图器类。

策略模式的优点显而易见:

  • 代码复用: 通过将算法或策略的实现与使用它们的环境分离,可以提高代码的可复用性。
  • 灵活设计: 策略模式可以使设计更具灵活性,便于在需要时更改算法或策略。
  • 扩展性强: 策略模式可以使代码具有很强的扩展性,当需要增加新的算法或策略时,只需实现一个新的策略类即可。

然而,策略模式也存在一些缺点和局限性:

  • 性能开销: 策略模式可能会带来一些性能开销,因为每次调用策略时都需要进行一次方法调用。
  • 代码复杂性: 策略模式可能会增加代码的复杂性,尤其是当策略数量较多时。
  • 维护成本: 策略模式可能会增加代码的维护成本,因为当需要更改算法或策略时,需要修改相应的策略类。

总的来说,策略模式是一种非常有用的设计模式,可以帮助我们应对变化,提高代码的可复用性和灵活性。在实际应用中,需要根据具体情况权衡策略模式的优点和缺点,以决定是否使用策略模式。