聊聊策略模式

聊聊策略模式

首先,需要明白策略模式的定义与使用场景:

  • 意图:定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。
  • 主要解决:在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。
  • 何时使用:一个系统有许多许多类,而区分它们的只是他们直接的行为。
  • 如何解决:将这些算法封装成一个一个的类,任意地替换。

明确了它的定义和用途后,可以建立一个类图,来理解和使用策略模式:

先给定一个场景,在数据交互的过程中,可能会出现很多的数据类型,但是如何对这些数据类型做处理,那就是比较麻烦的一件事。

这里提供了一个BaseDataHandler,去做了具体的实现。

public class BaseDataHandler implements Handler {

    @Override
    public void dataRead(Object obj) {
        if (obj instanceof DataA) {
            System.out.println("DataA:" + obj);
        } else if (obj instanceof DataB) {
            System.out.println("DataB:" + obj);
        }
    }
}
public class Main {
    public static void main(String[] args) {
        Handler handler = new BaseDataHandler();

        handler.dataRead(new DataA("Hello World"));
        handler.dataRead(new DataB("Hello World", "2020-05-07"));
    }
}
...
DataA:DataA{context='Hello World'}
DataB:DataB{context='Hello World', date='2020-05-07'}

可以看到BaseDataHandler里面有一些if else。但如果,数据类型变多了,那if else 岂不是也变多了?而且,这种代码一点也不够灵活。

为了解决这个问题,可以把不同的类型,交给不同的Handler来处理,我们可以把它称之为策略对象,并且通过工厂来创建这些不同的策略对象。

// 数据类型的枚举
public enum DataType {
    A,
    B,
}

// 策略的实现
public class DataAHandler implements Handler {
    @Override
    public void dataRead(Object data) {
        System.out.println("DataAHandler:" + data);
    }
}
public class DataBHandler implements Handler {

    @Override
    public void dataRead(Object obj) {
        System.out.println("DataBHandler:" + obj);
    }
}

// 策略的创建
public class DataHandlerFactory {
    private static final Map<DataType, Handler> strategies = new HashMap<>();

    static {
        try {
            strategies.put(DataType.A, DataAHandler.class.newInstance());
            strategies.put(DataType.B, DataBHandler.class.newInstance());
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    public static Handler get(DataType dataType) {
        return strategies.get(dataType);
    }
}

// 使用
public class Main {
    public static void main(String[] args) {
        Handler dataAHandler = DataHandlerFactory.get(DataType.A);
        Handler dataBHandler = DataHandlerFactory.get(DataType.B);

        dataAHandler.dataRead(new DataA("Hello World"));
        dataBHandler.dataRead(new DataB("Hello World", "2020-05-07"));
    }
}

这样就可以解决,我们在针对不同数据类型做处理时,需要通过写大量if else的糟糕代码。而且通过使用面向接口编程,之后这些Handler,想要再去做一些别的操作,也只需要去实现不同的接口即可。

在实际接触过的项目中就有遇到过这种问题,在没有使用策略模式的情况下,对于解码后的数据,大概有十几种类型都需要通过if else来做判断,把不同的数据,传递给不同的服务,这样的代码不仅极其难看,还难以维护。

但用了策略模式后,轻而易举的就解决了这个问题。

最后说一句,这里除了策略模式,还使用到了工厂模式,之后也专门会有文章来介绍工厂模式。

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×