假设有一个提供API的网站,例如:
GET
和
POST
个呼叫我现在拥有的东西看起来像这样:
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
。这是正确的方法吗?还是应该 only 方法返回访问令牌,然后将结果明确分配给类的字段? getQuestions
和getAnswers
方法也一样:它们两者都得到ArrayList
,返回它们并并分配一个{{1 }}的结果字段-都在单个方法内。
我希望User
类具有一定的意义。我想做这样的事情:
User
因此, Wrapper wrapper = new Wrapper(...);
User user = new User("username");
user.getQuestions(wrapper.getAccessToken());
user.sendMessage(wrapper.getAccessToken());
类仅用作从中获取访问令牌的地方,感觉也不好。我可以将访问令牌功能放在Wrapper
类中,并像这样使用它:
User
User user = new User("username", ...);
user.getQuestions();
user.sendMessage();
的构造函数将同时使用用户名和身份验证数据,将获取访问令牌并将其存储在用户内部,然后在获取问题/答案或发送消息时使用它。我可以在User
类accessToken
中创建User
字段,以便所有用户共享相同的令牌。
但是,网站API提供了一些显然与用户无关的操作:例如,获取网站最受欢迎的问题。为此目的使用通用的static
类是正确的,这与以前的方法相矛盾。
我对此并不陌生,只知道几种设计模式。也许,有广泛的模式可用于此类问题?任何帮助/建议,表示赞赏。
答案 0 :(得分:1)
您可以采取几种替代方法来解决问题,但是一个可能没有一个比其他所有方法都好。您选择的解决方案将取决于权衡以及您希望系统如何运行。以下是针对此类问题的两种常见解决方案。
让Wrapper
生成一个User
:您可以将User
与Wrapper
分开生成Wrapper
对象User
生成Wrapper
对象。这使AccessToken
可以将User
嵌入AccessToken
内,而没有任何外部客户端知道用户拥有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;
public User(String username, AccessToken token) {
this.user = user;
this.token = token;
}
// ... getters and setters ...
}
定义:
getAccessToken
请注意,private
现在是Wrapper
,因为没有其他客户端需要访问此方法。 User
的所有方法都继续接受getToken
参数,但是现在它们应该通过在User
对象上调用AccessToken
而不是使用存储的方法来获取访问令牌。 Wrapper
中的token
。
还请注意,final
字段为User
,因为与User
关联的访问令牌在Wrapper
对象的生命周期内不应更改。
将User
嵌入Wrapper
:此技术类似于(1),但它也将User
对象嵌入{ {1}}对象。这使User
类可以充当活动对象,可以向其查询问题和答案,并可以用于发送消息。由于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
对象获得问题和答案。请注意,findQuestions
和findAnswers
方法以find
开头。这提示客户端此调用可能是长调用(与getQuestions
或getAnswers
相对,这会使客户端假定这是一个简单的getter,并且该方法几乎立即返回)。这些方法执行远程调用的事实也应在Java-docs中记录这些方法。如果调用需要很长时间,则方法应返回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
类中可能是一个更好的主意。这是一个判断调用,将取决于您特定应用程序的性质。
您还可以使用许多其他方法,但是以上两种是解决您要解决的问题的常用方法。