设计模式

责任链模式(分离职责,动态组合)

2017-02-23  本文已影响251人  幺鹿

前言

登录、注册功能是日常开发中必备的功能,不管哪里都有它的身影。现在需要给客户提供一个注册功能,就如下图那样。

注册界面

需要输入头像、姓名、邮箱地址、电话、密码这些必填项之后,才能点击注册按钮。

假设我们已经可以正确取到每个元素(头像、姓名等)的值分解下实现过程:

正文

定义用户对象

用于封装数据提交验证。这样我们就可以构造多个用户对象,来验证职责链模式了。

public class User {

    public String name;
    public String avatar;
    public String email;
    public String phone;
    public String password;

    public User(String name, String avatar, String email, String phone, String password) {
        this.name = name;
        this.avatar = avatar;
        this.email = email;
        this.phone = phone;
        this.password = password;
    }
}

定义验证接口

定义验证接口此处命名为IDuty,不同的验证可以通过实现该接口来实现。这意味着对于客户端来说,每个职责的实现类都是平等的可替代的。

  • 验证头像格式是否正确(验证标准是含有http://字符串即认为通过)
public interface IDuty<User> {
    boolean verify(User user);
}

// 示意一个职责实现类
public class VerifyAvatarDutyImpl extends Duty {
    @Override
    public boolean verifyImpl(User user) {
        String avatar = user.avatar;
        if (avatar == null) return false;
        else if (avatar.contains("http://"))
            return true;
        return false;
    }
}

动态组合(构成链)

通过上述步骤,我们已经拆解了诸多验证职责。但是现有的资源,无法帮助我们构成链。

单链表节点
public abstract class Duty implements IDuty<User> {

    private Duty nextDuty;
    private Duty prevDuty;

    public Duty setNext(Duty next) {

        if (next == null) throw new IllegalArgumentException("duty can not be null.");

        Duty temp = moveToLast();

        temp.nextDuty = next;
        next.prevDuty = temp;

        return next;
    }

    @Override
    public final boolean verify(User user) {
        final boolean bool = verifyImpl(user);
        System.out.println("[" + getClass().getSimpleName() + "] verify :" + bool);
        if (!bool) {
            debugPrint(bool);
            return bool;
        } else {
            if (nextDuty != null) {
                return nextDuty.verify(user);
            } else {
                debugPrint(bool);
                return bool;
            }
        }
    }

    private void debugPrint(boolean bool) {
        if (!bool)
            System.out.println("[" + getClass().getSimpleName() + "] 被迫终止");
        else
            System.out.println("[" + getClass().getSimpleName() + "] 恭喜校验通过");
    }

    public Duty moveToFirst() {
        Duty firstDuty = this;
        while (firstDuty.prevDuty != null) {
            firstDuty = firstDuty.prevDuty;
        }
        return firstDuty;
    }

    protected abstract boolean verifyImpl(User user);
}

客户端验证,为了避免一些书写错误。在这里直接定义了 setNext()方法,用于构造链式函数。并且提供了moveToFirst()方法,用于将指针移动到链表中的第一个元素并发起顺序调用。

  public class Client {

    public static void main(String[] atgs) {

        User user = new User("幺鹿幺鹿幺鹿", "http://www.jianshu.com", "chenjunqi.china@gmail.com", "18668247775", "1234567");

        new VerifyAvatarDutyImpl()
                .setNext(new VerifyRealNameDutyImpl())
                .setNext(new VerifyEmailDutyImpl())
                .setNext(new VerifyPhoneDutyImpl())
                .setNext(new VerifyPasswordDutyImpl())
                .moveToFirst() // 为了移动到 VerifyAvatarDutyImpl 对象,然后发起顺序的链式验证
                .verify(user);

    }
}

执行客户端的打印结果

[VerifyAvatarDutyImpl] verify :true
[VerifyRealNameDutyImpl] verify :true
[VerifyEmailDutyImpl] verify :true
[VerifyPhoneDutyImpl] verify :true
[VerifyPasswordDutyImpl] verify :true
[VerifyPasswordDutyImpl] 恭喜校验通过

总结

责任链模式本质:分离职责,动态组合。

职责链模式.png

番外篇

提起职责链模式,让我就联想起 Android 的事件投递

上一篇下一篇

猜你喜欢

热点阅读