java - Java中的第三方API包装器: how to design

标签 java api oop design-patterns

假设有一个网站提供 API,如下所示:

  • 用户在该网站上发布问题和答案
  • 您可以进行 GETPOST 调用
  • 有两种类型的身份验证:(仅给出 读取权限)和(同时提供读取和写入权限)
  • 现在,我想阅读用户的问题和答案(仅需要弱访问权限)并向他们发送消息或将来发布我自己的问题(需要强访问权限)
  • 网站的 API 具有两者与用户(例如发送消息)和一般网站相关的操作(查看有关信息、查看最常见的问题)

我现在拥有的看起来像这样:

public class Wrapper  {
   private AccessToken accessToken;

   public Wrapper(...)  {
     //does some stuff
     //gets access token:
     getAccessToken(...);
   }    

   public AccessToken getAccessToken(...)  {
      AccessToken result;
      //gets access token, given the auth info provided as arguments
      accessToken = result;

      return result; 
   }

   public ArrayList<Question> getQuestions(User user)  {
       //gets user's questions, using the accessToken field
       //set's a user's questions field to the result and returns the result
   }

   public ArrayList<Answer> getAnswers(User user)  {
       //same as previous
   }

   public boolean sendMessage(User user)  {
      //sends a message, if current accessToken is strong
   }
}

用户类别:

class User  {
  private String username;

  private ArrayList<Question> questions;
  private ArrayList<Answer> answers;

  public User(String username) {this.username=username;}    

  //getters and setters
}

因此,要使用它,您可以使用如下内容:

public class Main  {
  public static void main(String[] args)  {
     Wrapper wrapper = new Wrapper(...);
     ArrayList<Question> questions = wrapper.getQuestions(new User("username"));
     wrapper.sendMessage(new User("username2"));
  }
}

我对此有疑问。

首先,User 类感觉是多余的,因为所有功能都在 Wrapper 类中。

其次,我想知道我的方法所做的是否正确 - 从设计的角度来看:在 getAccessToken 中,我两者都返回 AccessToken Wrapper的字段accessToken设置为结果。这是正确的方法吗?或者方法应该返回访问 token ,然后将该结果显式分配给类的字段? getQuestionsgetAnswers 方法也是如此:它们获取ArrayList,返回它们用户的字段分配给结果 - 全部在单个方法内。

我希望 User 类具有一定的意义。我想过这样做:

    Wrapper wrapper = new Wrapper(...);

    User user = new User("username");
    user.getQuestions(wrapper.getAccessToken());
    user.sendMessage(wrapper.getAccessToken());

因此,Wrapper 类只能充当获取访问 token 的位置,这感觉也不对。我可以将访问 token 功能放置在 User 类中并按如下方式使用它:

     User user = new User("username", ...);
     user.getQuestions();
     user.sendMessage();

User 的构造函数将获取用户名和身份验证数据,获取访问 token 并将其存储在用户内部,然后在获取问题/答案或发送消息时使用它。我可以在 Userstatic 中设置 accessToken 字段,以便所有用户共享相同的 token 。

但是,网站 API 提供的某些操作与用户没有明显的联系:例如,获取网站 HitTest 门的问题。为此目的使用通用 Wrapper 类感觉是正确的,但这与之前的方法相矛盾。

我对此很陌生,只知道几种设计模式。也许有广泛的模式可用于解决此类问题?如有任何帮助/建议,我们将不胜感激。

最佳答案

您可以采取一些替代方案来解决您的问题,但可能没有一个比所有其他方案都更好。您选择的解决方案将取决于权衡以及您希望系统如何运行。以下是此类问题的两种常见解决方案。

  1. 拥有 Wrapper生成 User :而不是生成 UserWrapper 分开的对象,您可以拥有Wrapper生成User目的。这允许 Wrapper嵌入AccessToken User内没有任何外部客户端知道用户有 AccessToken 。例如,您可以使用以下 WrapperUser定义:

    public class Wrapper  {
    
       public Wrapper(...)  {
           // ... does some stuff, but DOES NOT get an access token ...
       }    
    
       private AccessToken getAccessToken(...)  {
           AccessToken result;
           // ... gets access token, given the auth info provided as arguments ...
           return result; 
       }
    
        public User findUser(String username, ...) {
            return new User(username, getAccessToken(...));
        }
    }
    
    class User  {
    
        private String username;
        private final AccessToken token;
    
        public User(String username, AccessToken token) {
            this.user = user;
            this.token = token;
        }
    
        // ... getters and setters ...
    }
    

    请注意getAccessToken现在是private ,因为没有其他客户端需要访问此方法。 Wrapper的所有方法继续接受User参数,但他们现在应该通过调用 getToken 来获取访问 token 关于User对象,而不是使用存储的 AccessTokenWrapper

    另请注意 token字段是 final ,因为访问 token 与 User 关联User 的整个生命周期中不应发生变化对象。

  2. 嵌入 WrapperUser :这种技术与(1)类似,但它也嵌入了Wrapper User 中的对象目的。这允许 User类充当 Activity 对象,可以查询问题和答案,并可用于发送消息。由于 Wrapper 的所有方法接受User论点,这是一个好兆头,表明这些方法应该移至 User 。下面是重构的中途点Wrapper方法进入User :

    public class Wrapper  {
    
       public Wrapper(...)  {
           // ... does some stuff, but DOES NOT get an access token ...
       }    
    
       private AccessToken getAccessToken(...)  {
           AccessToken result;
           // ... gets access token, given the auth info provided as arguments ...
           return result; 
       }
    
        public User findUser(String username, ...) {
            return new User(username, getAccessToken(...));
        }
    
        public ArrayList<Question> getQuestions(User user)  {
            //gets user's questions, using the accessToken field
            //set's a user's questions field to the result and returns the result
        }
    
        public ArrayList<Answer> getAnswers(User user)  {
            //same as previous
        }
    
        public boolean sendMessage(User user)  {
            //sends a message, if current accessToken is strong
        }
    }
    
    class User  {
    
        private String username;
        private final AccessToken token;
        private final Wrapper wrapper;
    
        public User(String username, AccessToken token, Wrapper wrapper) {
            this.user = user;
            this.token = token;
            this.wrapper = wrapper;
        }
    
        public List<Question> findQuestions() {
            return wrapper.getQuestions(this);
        }
    
        public ArrayList<Answer> findAnswers()  {
            return wrapper.getAnswers(this);
        }
    
        public boolean sendMessage()  {
            return wrapper.sendMessage(this);
        }
    
        // ... getters and setters ...
    }
    

    使用这种技术,客户现在可以直接从 User 获取问题和答案。目的。请注意 findQuestionsfindAnswers方法以 find 开头。这会提示客户端此调用可能是一个长调用(与 getQuestionsgetAnswers 相反,这会让客户端认为它是一个简单的 getter 并且该方法将几乎立即返回)。这些方法执行远程调用的事实也应该记录在这些方法的 Java 文档中。如果调用需要很长时间,这些方法应该返回 Future (或类似的对象)并异步制作。

    如果您想全力进行重构,您可以将所有实现细节从Wrapper移走。类到 User类:

    public class Wrapper  {
    
       public Wrapper(...)  {
           // ... does some stuff, but DOES NOT get an access token ...
       }    
    
       private AccessToken getAccessToken(...)  {
           AccessToken result;
           // ... gets access token, given the auth info provided as arguments ...
           return result; 
       }
    
        public User findUser(String username, ...) {
            return new User(username, getAccessToken(...));
        }
    }
    
    class User  {
    
        private String username;
        private final AccessToken token;
        private final Wrapper wrapper;
    
        public User(String username, AccessToken token, Wrapper wrapper) {
            this.user = user;
            this.token = token;
            this.wrapper = wrapper;
        }
    
        public List<Question> findQuestions() {
            // ... find the questions remotely ...
        }
    
        public ArrayList<Answer> findAnswers()  {
            // ... find the answers remotely ...
        }
    
        public boolean sendMessage()  {
            // ... send message remotely ...
        }
    
        // ... getters and setters ...
    }
    

    这可能不是最好的方法,因为将访问远程 API 的详细信息保留在 Wrapper 中可能是更好的主意。类(class)。这是一个判断,取决于您的具体应用程序的性质。

您还可以使用许多其他技术,但以上两种是解决您要解决的问题的常见方法。

关于java - Java中的第三方API包装器: how to design,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55131566/

相关文章:

iphone - ASIHTTPRequest代码设计

java - 对象如何取消标记接口(interface)的标记?

typescript - 类与接口(interface)作为 typescript 中的类型

java - 为什么Android中的MessureSpec常量是-2147483648, 1073741824, 0

java - 如何获取jar类来自

api - 使用 Security REST 插件保护 REST API 的安全

rest - 使用 HATEOAS 对耦合的 RESTful API 进行版本控制

Java - OSX Mavericks 上的 Accumulo init 异常 - log4j 记录器

java - Hibernate 通用 DAO、通用服务和通用 View 层?

java - #Askfirebase 在 android 中的 firebase 回收器适配器中获取上一个项目值(POJO)