我正在使用MVC架构。
SignupController从SignupView创建一个User对象。
该用户应存放在哪里?
我已经尝试将其存储到MainController中,但是当我需要访问User对象时,我需要再次初始化MainController,因此User现在为null。
谢谢!
答案 0 :(得分:1)
好的,让我们后退一步。 User
是数据,在此内容中,数据应由模型层管理和维护。
控制器负责协调视图和模型之间的操作和通知。在这个意义上,当用户在视图中触发请求(即执行注册操作)时,视图会触发控制器订阅的事件。控制器从视图中获取所需信息并将该信息传递给模型。这可能会向后工作,模型会根据任务的成功触发事件,控制器会根据需要通知视图
这一切的重要部分,是没有人知道其他部分是如何运作的......并且不关心
让我们从基础开始。您需要某种方式来表示"用户"
public interface User {
public String getName();
}
现在,您需要创建一个User
...
public interface UserFactoryListener {
public void userCreated(User user);
public void userCreationFailed(Exception exp); // Or some other error object
}
public interface UserFactory {
public void makeUser(String name);
public void addUserFactoryListener(UserFactoryListener listener);
public void removeUserFactoryListener(UserFactoryListener listener);
}
所以,这是一个工厂的基本概念,它将取用户的名字并创建一个新的User
对象,这里需要注意的重要一点是,我们不在乎&#34 ;如何"完成后,只有这样做,并且它将生成成功或失败事件
但是,如果我们还希望能够对用户进行身份验证呢?
public interface UserAuthenticationistener {
public void userAuthenticated(User user);
public void userAuthenticationFailed(Exception exp); // Or some other error object
}
public interface UserAuthenticator {
public void authenticateUser(String name, char[] password) throws SecurityException;
public void addUserAuthenticator(UserAuthenticator listener);
public void removeUserAuthenticator(UserAuthenticator listener);
}
所以,这是一个基本的想法,它需要一个名称和密码,并在某种程度上验证用户,我们不关心,并将产生我们可以订阅的成功或失败事件。 / p>
"是的,但用户模型怎么样?" 我听到你说,很高兴你问过!
public interface UserSigninModel extends UserFactory, UserAuthenticator {
}
嗯,好吧,这是登录模型,但它包含了我们想要支持,注册或登录的两个主要功能。
现在,我们需要一些方法来协调两者,这是控制器的工作......
public interface UserSigninController extends UserSigninViewListener, UserFactoryListener, UserAuthenticationistener {
public UserSigninModel getModel();
public UserSigninView getView();
}
......好吧,这有点令人印象深刻,但这就是重点
最后,我们需要一些方法来与实际用户进行交互,即视图!
public interface UserSigninViewListener {
public void signupUser(UserSigninView view);
public void authenticateUser(UserSigninView view);
}
public interface UserSigninView {
public Pane getView();
public String getName();
public char[] getPassword();
public void addUserSigninViewListener(UserSigninViewListener listener);
public void removeUserSigninViewListener(UserSigninViewListener listener);
public void userSignupFailed(Exception exp);
public void userAuthenticationFailed(Exception exp);
}
所以,所有这一切都做了一件简单的工作。它描述了每个层预期提供的意图(或合同)。任何一方都没有真正关心其他部分是如何实施的,只是合同得到维护
例如,可能的控制器实现看起来像......
public class DefaultUserSigninController implements UserSigninController {
private UserSigninModel model;
private UserSigninView view;
public DefaultUserSigninController(UserSigninModel model, UserSigninView view) {
this.model = model;
this.view = view;
}
@Override
public UserSigninModel getModel() {
return model;
}
@Override
public UserSigninView getView() {
return view;
}
@Override
public void signupUser(UserSigninView view) {
getModel().makeUser(view.getName());
}
@Override
public void authenticateUser(UserSigninView view) {
getModel().authenticateUser(view.getName(), view.getPassword());
}
@Override
public void userCreated(User user) {
// Coordinate with the navigation controller to move to the
// next part of the program. This might pass the User object
// to the navigation controller (as a event) so it
// can be seeded into the next model
}
@Override
public void userCreationFailed(Exception exp) {
getView().userSignupFailed(exp);
}
@Override
public void userAuthenticated(User user) {
// Coordinate with the navigation controller to move to the
// next part of the program. This might pass the User object
// to the navigation controller (as a event) so it
// can be seeded into the next model
}
@Override
public void userAuthenticationFailed(Exception exp) {
getView().userAuthenticationFailed(exp);
}
}
控制器本身并没有做很多事情,除此之外协调视图和模型之间的通信。它还提供了向另一个"导航控制器提供通知的可能性。可能负责确定下一个应显示哪个控制器/视图。它甚至可能创建" base"模型包装新的User
对象。
这是一个过于简化的例子,旨在提供一个可证明的工作流程概念 - 重点是,"如何"并不重要,因为它应该隐藏在interface
之后,每个层同意实施的合同至关重要。
此外,我的JavaFX很小,因此可以更改事件管理以更好地适应API实际如何实现它的可观察模式
答案 1 :(得分:0)
据我所知,基于fxml
标记,您正在使用Java FX构建应用程序,这意味着应用程序中任何时候只有一个User
。在这种情况下,最好的方法是将其存储在一个单独的类中,如服务或存储库。
示例:
public class UserService {
protected User user;
public Optional<User> getUser() {
return Optional.ofNullable(user);
}
public void setUser(User user) {
this.user = user;
}
}
然后使用Dependency Injection(例如Guice)或某种Singleton Pattern实施,例如getInstance()
。
如果您正在讨论Web应用程序,我建议在会话中保留引用,因为这会将User
绑定到执行HTTP请求的实际用户。