策略模式-实例(登录类设计)

面试被问到:使用“开闭原则”、“面向对象”的思想,设计一个登录类,涉及账号密码登录、手机号码登录什么的

当时(现在也)觉得是策略模式的应用,但是具体怎么写就…
现在来实现一遍

Round.1

首先我们设计了一个顶级父类Login,然后分别用两个子类("账号密码登录类"和"手机验证码登录类"来继承它)

为什么这里一开始是用继承而不是用接口呢?
因为有一些公共的代码实现,比如logout()方法需要复用,完全每必要重写

/**
* 登录类顶级父类
* @author yao 2022/12/8
*/
public abstract class Login {
/**
* 登录
*/
abstract void login();
/**
* 注销
*/
void logout(){
System.out.println("用户注销,退出登录");
}
}
/**
* 账号密码登录
* @author yao 2022/12/8
*/
public class AccountLogin extends Login{
@Override
public void login() {
System.out.println("使用账号密码登录");
}
}
/**
* 手机号码登录
* @author yao 2022/12/8
*/
public class PhoneNumberLogin extends Login{
@Override
void login() {
System.out.println("使用手机号码验证码登录");
}
}

目前看来还行,我可以使用多态来调用

/**
* @author yao 2022/12/8
*/
public class TestLogin {
public static void main(String[] args) {
Login login = new AccountLogin();
login.login();
login.logout();
login = new PhoneNumberLogin();
login.login();
}
}

使用账号密码登录
用户注销,退出登录
使用手机号码验证码登录

Round.2

然后变化来了:来了一个部分子类有,部分子类没有的方法

更进一步,不仅部分子类有,部分子类没有,有该方法的对象执行该方法的表现还不一样

举个例子,比如:注册
注册只有“手机验证码登录”和“账号密码登录类”有,因为这两个是自己管理的,但是调用第三方认证的登录类比如“QQ登录”是没有的

不确定这个例子是否足够好

那么矛盾就出来了:

  1. 如果直接修改超类,添加一个方法?
    显然是不合适的,因为不是每个子类都应该有这个方法

覆盖成空实现?
听起来做法很蠢,要检查每一个不符合的方法,然后都覆盖一遍?!随着子类越来越多这是无法忍受而且极易出错的
直接改动原来的代码也是不符合“开闭原则”的

  1. 把超类改成接口?
    似乎也是不合适的,和上面一样,不是每个子类都需要实现这个方法
  2. 那考虑把有些子类有、有些子类没的方法再抽象成接口?
    这样的话对于共有的代码逻辑,比如logout(),就不得不在每一个子类中写一遍,不优雅不满足代码复用

设计原则:
把会变化的部分取出来并封装起来,以便以后可以轻易地改动或扩充此部分,而不影响不需要变化的其他部分

在这里会变化的就是对象的行为,即注册
把注册抽象为接口,同时为这个接口提供不同的实现
顶级父类添加这个接口对象替代原来的方法
并且对具体的实现也不是自己完成,而是委托给接口对象

Register register;
/**
* 不亲自处理注册逻辑,而是委托给接口对象
*/
public void performRegister(){
register.register();
}

然后子类可以在构造方法中按需实例化这个接口对象,不同的实例

public PhoneNumberLogin(){
register = new PhoneRegister();
}

但是这样是有问题的,如果我调用了我本不应该有的行为,因为没有实例化对象,会报空指针异常的

改进成在顶级父类中提供set()方法设置接口对象,这样虽然可以动态设置,但是没办法保证一定被设置

…烦,又乱了

本文作者:YaosGHC

本文链接:https://www.cnblogs.com/yaocy/articles/16965920.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   YaosGHC  阅读(68)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起