设计模式(六):策略模式
目录
概述
将不同的内部算法封装成不同策略,调用者可以根据在调用的时候主动控制不同策略,实现同一功能。例如:登录这个功能,系统内部支持多种策略:手机验证码,用户名密码,微信号,QQ号登录等。
场景介绍
登录接口,有个login方法
public interface Login {
void dologin(String name, String pwd);
}
分别有两个实现类,用户名密码登录,微信登录
public class UserNameLogin implements Login{
@Override
public void dologin(String name, String pwd) {
System.out.println("用户名 密码正确 登录成功");
}
}
public class WeixinLogin implements Login{
@Override
public void dologin(String name, String pwd) {
System.out.println("正在调用微信登录接口... 验证成功");
}
}
创建枚举类,确定策略与实现类的映射关系
public enum LoginStrategy {
WEIXIN(new WeixinLogin()),USERNAME(new UserNameLogin());
private Login login;
LoginStrategy(Login login) {
this.login = login;
}
public Login getLogin() {
return login;
}
}
封装服务
public class LoginService {
void login(String username, String pwd, LoginStrategy strategy){
strategy.getLogin().dologin(username, pwd);
}
}
测试类
public class LoginStrategyTest {
public static void main(String[] args) {
LoginService wxLoginService = new LoginService();
wxLoginService.login("wwh","123", LoginStrategy.USERNAME);
//输出:用户名 密码正确 登录成功
wxLoginService.login("wx123","wx123", LoginStrategy.WEIXIN);
//输出:正在调用微信登录接口... 验证成功
}
}
总结
调用者可以根据自己的需求用不同算法实现功能,
利用枚举的最大好处在于
- 语义清晰,不然会有很多内定的含义,比如,微信的时候你调用这个接口最后的参数传1,用户名密码的时候传2
- 当支持新增策略的时候,调用放能够很快的感知
策略模式还有一个特点,具体的实现逻辑是包含在枚举内部的,枚举类还有一定的分发功能,维护枚举对象到实现的映射关系
策略模式 + 委派模式
下面给大家举个策略模式+委派模式的例子。从想表达这个例子,到做成demo思考了很多,感觉对设计帮助很大,也能更好地区分这两种模式的区别,所以在这里分享出来。
来了来了
- 首先定义新的枚举类,相比之前的类明显的区别在于不需要依赖具体的实现类了
public enum LoginStrategyPlus {
WEIXIN(1),USERNAME(2);
private int loginType;
LoginStrategyPlus(int loginType) {
this.loginType = loginType;
}
public int getLoginType() {
return loginType;
}
}
- 然后定义策略模式+委派模式的核心服务类,在静态方法中初始化了一个map用来维护,策略到实现类的关系,然后委派具体的实现类执行
public class LoginStrategyDelegatePlus {
private static Map<LoginStrategyPlus, Login> typeLoginMap = new HashMap<>();
static {
typeLoginMap.put(LoginStrategyPlus.WEIXIN, new WeixinLogin());
typeLoginMap.put(LoginStrategyPlus.USERNAME, new UserNameLogin());
}
public void login(String username, String pwd, LoginStrategyPlus loginStrategyPlus){
typeLoginMap.get(loginStrategyPlus).dologin(username, pwd);
}
}
- 创建测试类
public class LoginStrategyDelegateTest {
public static void main(String[] args) {
LoginStrategyDelegatePlus loginStrategyDelegatePlus = new LoginStrategyDelegatePlus();
loginStrategyDelegatePlus.login("wx123", "pwd123", LoginStrategyPlus.WEIXIN);
//输出:正在调用微信登录接口... 验证成功
loginStrategyDelegatePlus.login("uname123", "pwd123", LoginStrategyPlus.USERNAME);
//输出:用户名 密码正确 登录成功
}
}
总结
策略模式+委派模式的实现将策略和委派业务分离,在委派的业务场景复杂,在经常需要扩展或者修改分发逻辑的的场景下更具有扩展性。
单纯的使用策略模式在新建枚举类型时调用者可以看到具体的实现类,但是第二种模式封装的更加彻底。
所以说策略模式其实包含了简单的分发逻辑,策略和委派更像是你中有我我中有你的感觉。设计模式之间不需要区分的特别明确,可以根据实际场景修改。