设计模式-外观模式

外观模式

面对一个庞大且复杂的系统,我们很难去记住每个使用方法和它们之间的关系,我们需要一个东西帮我们简化整个系统,让我们能快速上手使用这个系统

概念

为子系统的一组接口提供一个统一的高层接口,在外部与一个子系统打交道只需要与一个对象交互即可。外观模式,又称门面模式,是 一种对象结构形模式

角色

  • Facade
    简单窗口,是向外部系统提供的高阶接口,比如Web后端接口
  • SubSystem
    子系统,在一个软件系统中可以有多个子系统,子系统不知道客户端的存在
  • Client
    客户端,使用Facade的角色,实际并不算入Facade模式内

外观模式的目的在于降低系统的复杂程度,简单来看是接口(Api)变少了,使用更简单了,并且降低了类与类之间的耦合度

案例

模拟一套较完整的用户注册登录认证流程,尽可能让用户无感知,要求:

  • 用户输入账号、密码和身份(普通和超管)注册
  • 用户输入账号密码登录
  • 注册要保证账号不重复
  • 判断账号密码正确性,正确则成功登录,并将用户的账号和权限签名为一个token返回去
  • 已登录时,重复登录,可以刷新token的时间,但不提醒用户
  • 有2个资源(base, plus)可供访问,后者只有超管能访问

用户子系统

User

public class User {
    private String name;
    private String pwsd;
    private String role;
    private String token;
    // 省略了构造,get/set,和euqal
    // equal的判断依据是name和pwsd都相等
}   

UserList

import java.util.ArrayList;

public class UserList {
    private ArrayList<User> users;

    public UserList() {
        users = new ArrayList<>();
    }

    public User find(User user){
        int index = users.indexOf(user);
        return index!=-1?users.get(users.indexOf(user)):null;
    }

    public void add(User user){
        users.add(user);
    }
}

Token

import java.util.HashMap;
import java.util.Map;

public class Token {
    public String value;

    private Token(User user) {
        Map<String,String> payloads = new HashMap<>();
        payloads.put("name", user.getName());
        payloads.put("role", user.getRole());
        value = payloads.toString();
    }

    public static Token sign(User user) {
        return new Token(user);
    }

    public static Map<String, String>  getPayloads(String v) {
        v = v.substring(1, v.length()-1);
        String[] subs = v.split(",");
        Map<String,String> payloads = new HashMap<>();
        for (String substring : subs) {
            String key = substring.split("=")[0];
            String value = substring.split("=")[1];
            String key1 = key.trim();
            String value1 = value.trim();
            payloads.put(key1, value1);
        }
        return payloads;
    }

    public Map<String, String> getPayloads() {
        String v = value;
        return getPayloads(v);
    }
}

Auth

public class Auth {
    public static boolean checkLogin(User user) {
        return user.getToken()!=null;
    }
    public static boolean checkRole(String resource, User user) {
        if (resource.equals("plus")){
            return Token.getPayloads(user.getToken()).get("role").equals("超管");
        }
        return true;
    }
}

用户子系统仅仅为了简单模拟一下用户注册登录认证,就创建了这么多类和方法,如果直接丢给客户端用,既让人懵逼也不安全,因此我们要封装一个高级接口,利用用户系统,提供3个功能即可,即login(登录),register(注册)和logout(登出)

UserFacade

import UserSystem.Auth;
import UserSystem.Token;
import UserSystem.User;
import UserSystem.UserList;

public class UserFacade {
    private UserList userList = new UserList();

    void register(String name, String pwsd, String role) {
        User user = new User(name, pwsd, role);
        User user1 = userList.find(user);
        if (user1!=null){
            System.out.println("已注册过");
        }
        userList.add(user);
        System.out.println("注册成功");
    }

    User login(String name, String pwsd) {
        User user = new User(name, pwsd);
        User user1 = userList.find(user);
        if (user1!=null){
            if (user.getToken()==null){
                System.out.println("登录成功");
            }
            Token token = Token.sign(user);
            user.setToken(token.value);
        } else {
            System.out.println("登录失败");
        }
        return user;
    }

    User logout(User user){
        user.setToken(null);
        return user;
    }

    boolean visit(String resource, User user) {
        if (!Auth.checkLogin(user)) {
            System.out.println("请先登录");
            return false;
        };
        if (!Auth.checkRole(resource, user)) {
            System.out.println("没有权限");
            return false;
        };
        return true;
    }
}

UserFacade封装好了注册、登入和登出的流程,并且还打印了反馈信息,只需寥寥几个参数即可使用,接着我们在Main(客户端)中使用UserFacade注册一个普通账号并登入它去访问指定资源

Client

import UserSystem.User;

public class Main {
    public static void main(String[] args) {
        UserFacade userFacade = new UserFacade();

        //注册
        userFacade.register("evan", "123", "普通");
        //登录1
        User user = userFacade.login("evan", "root");
        //登录2
        user = userFacade.login("evan", "123");
        //访问plus
        userFacade.visit("plus", user);
        //退出登录
        user = userFacade.logout(user);
        //访问base
        userFacade.visit("base", user);

    }
}

Output:

D:\Develop-Environment\Java\jdk-1.8\bin\java.exe...
注册成功
登录失败
登录成功
登录失败
没有权限
请先登录

用了UserFacade,客户马上就能明白怎么捣鼓他的账号,这就是外观模式的妙处。据统计,外观模式可是我们在项目开发中最广泛应用到的一种设计模式,很多时候子系统代码层次较多,为了方便开发者专注于较上层,在中间也会加一层外观者。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值