贯穿设计模式-适配器模式+桥接模式

149 阅读2分钟

引言

样例所有代码可以github.com/WeiXiao-Hyy…获取,欢迎Star!

适配器模式

类似于补丁的方式,如果频繁使用会导致类爆炸

适配器模式.png

// 可以采用继承的方式
public class Login3rdAdapter extends UserService implements Login3rdTarget {

}

// 可以采用组合的方式
public class Login3rdAdapter implements Login3rdTarget {

    @Autowired
    private UserService userService;
}

@Override
public String loginByGitee(String code, String state) {
    // 准备请求参数
    prepareAccessTokenReq(code, state);

    //调用方法得到accessToken
    String accessToken = getAccessToken(accessTokenDTO);

    //调用方法得到用户信息
    GiteeUser user = getUser(accessToken);

    // 自动注册和登陆
    return autoRegister3rdAndLogin(user);
}

private String autoRegister3rdAndLogin(GiteeUser giteeUser) {
    //判断是否为null
    if (Objects.isNull(giteeUser)) {
        return "user is not exists";
    }

    //获取用户名和密码
    String userName = user_prefix + giteeUser.getName();
    String password = giteeUser.getName();

    //如果存在则直接登陆
    if (super.checkUserExists(userName)) {
        return super.login(userName, password);
    }

    //不存在则先注册再登陆
    UserInfo user = UserInfo.builder()
            .userName(userName)
            .password(password)
            .email(giteeUser.getEmail())
            .build();

    super.register(user);

    return super.login(userName, password);
}

桥接模式

桥接模式.png

public abstract class AbstractRegisterLoginFunc implements IRegisterLoginFunction {

    protected String commonLogin(String account, String password, UserMapper userRepo) {
        UserInfo userInfo = userRepo.findByNameAndPassword(account, password);
        if (Objects.isNull(userInfo)) {
            return "account / password ERROR!";
        }
        return "Login Success!";
    }

    protected String commonRegister(UserInfo userInfo, UserMapper userRepo) {
        if (commonCheckUserExists(userInfo.getUserName(), userRepo)) {
            throw new RuntimeException("User already registered.");
        }
        userRepo.insert(userInfo);
        return "Register Success!";
    }

    protected boolean commonCheckUserExists(String userName, UserMapper userRepo) {
        UserInfo user = userRepo.findByUserName(userName);
        return null != user;
    }

		// 让其实现子类,不需要实现所有的方法
    public String login(String account, String password) {
        throw new UnsupportedOperationException();
    }

    public String register(UserInfo userInfo) {
        throw new UnsupportedOperationException();
    }

    public boolean checkUserExists(String userName) {
        throw new UnsupportedOperationException();
    }

    public String login3rd(HttpServletRequest request) {
        throw new UnsupportedOperationException();
    }
}

// 没有实现login3rd但没有报错
@Component
public class RegisterLoginByDefault extends AbstractRegisterLoginFunc implements IRegisterLoginFunction {

    @Autowired
    private UserMapper userRepo;

    @Override
    public String login(String account, String password) {
        return super.commonLogin(account, password, userRepo);
    }

    @Override
    public String register(UserInfo userInfo) {
        return super.commonRegister(userInfo, userRepo);
    }

    @Override
    public boolean checkUserExists(String userName) {
        return super.commonCheckUserExists(userName, userRepo);
    }
}

优化点

public String login(String account, String password) {
    //每次执行login的时候都需要创建两个对象,可能会引起频繁垃圾回收
    AbstractRegisterLoginComponent registerLoginComponent = new RegisterLoginComponent(new RegisterLoginByDefault());
    return registerLoginComponent.login(account, password);
}

public static final Map<String, AbstractRegisterLoginComponent> componentMap
            = new ConcurrentHashMap<>();

public static Map<String, IRegisterLoginFunction> funcMap
        = new ConcurrentHashMap<>();

/**
 * 根据不同的登陆类型,获取AbstractRegisterLoginComponent
 *
 * @param type 类型
 * @return {@link AbstractRegisterLoginComponent}
 */
public static AbstractRegisterLoginComponent getComponent(String type) {
    AbstractRegisterLoginComponent component = componentMap.get(type);

    // 双重检查锁设计
    if (Objects.isNull(component)) {
        synchronized (componentMap) {
            component = componentMap.get(type);
            if (Objects.isNull(component)) {
				//由于concurrentHashMap本身是并发安全的,所有不需要volatile
                component = new RegisterLoginComponent(funcMap.get(type));
                componentMap.put(type, component);
            }
        }
    }

    return component;
}

参考资料

在某些JVM当中,编译器为了性能问题,会进行指令重排。在上述代码中new Singleton()并不是原子操作,有可能会被编译器进行重排操作。

memory = allocate();    //1:分配对象的内存空间
ctorInstance(memory);  //2:初始化对象
instance = memory;     //3:设置instance指向刚分配的内存地址

指令重排之后可能会变成以下顺序

memory = allocate();    //1:分配对象的内存空间 
instance = memory;     //3:instance指向刚分配的内存地址,此时对象还未初始化
ctorInstance(memory);  //2:初始化对象