引言
样例所有代码可以github.com/WeiXiao-Hyy…获取,欢迎Star!
适配器模式
类似于补丁的方式,如果频繁使用会导致类爆炸
// 可以采用继承的方式
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);
}
桥接模式
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:初始化对象