为 Presenter、Model 或 Command 添加更多逻辑,从而将其从 View 中删除。这通常是更好的方法。考虑Single Responsibility principle 并从View 中移动应用程序/域逻辑。
您可以通过以下几种方式做到这一点:
在您的情况下,您需要将 NfcAdapter 从 View 到 Presenter 和 Command (如果你有)。
您可以通过以下几种方式做到这一点:
- 在 Presenter 的构造函数中传递它
- 在Presenter中添加一个特殊的initialization方法,并将它需要的所有依赖传递给这个方法(
public void initialize(NfcAdapter adapter, ...))
- 向 View 添加一个方法,Presenter 可以在需要时调用以获取适配器 (
NfcAdapter view.getAdapter())。
- 将其作为参数传递给方法调用(就像您所做的那样);
选择一种方法取决于几个因素,开发人员的喜好是其中之一。我个人会选择方法 1 或 2。我喜欢初始化对象的依赖关系(在这种情况下为 Presenter)在它的生命周期的乞求时,如果这个对象将一直需要它们并且它们不会改变。如果每次调用此方法时它们都更改,则将它们传递到方法调用中。在这种情况下,我认为您不会更改 NfcAdapter。
让我们设计一个命令。因为您有一个相当笼统的描述并且没有描述确切的顺序(first_call()、second_call() 太笼统),所以我将设计一个简单的非特定系统来进行几次调用。我将使用伪代码。大多数事情都是非具体的,因为我不知道返回类型和东西。
我们称这个命令为 CalculateCommand。此命令将使用 CalculationModel 进行计算。接下来让我们定义一个 TokenService,它将包含获取令牌(API 调用)的逻辑。
public class TokenService {
public SessionToken getToken() { ... }
}
public class CalculationResult {
// represent whatever the result is...
}
public class CalculateCommand {
private NfcAdapter mNfcAdapter;
private TokenService mTokenService;
private CalculationModel mCalculationModel;
private SessionToken mSessionToken;
public CalculateCommand(
NfcAdapter nfcAdapter,
TokenService tokenService,
CalculationModel calculationModel) {
mAdapter = adapter;
mTokenService = tokenService;
mCalculationModel = calculatioModel;
}
public CalculationResult Execute() {
startSession();
// do more stuff if you need to
val result = calculate();
return result;
}
private void startSession() {
mSessionToken = mTokenService.getToken();
}
private Result calcualte() {
//not sure what parameters it needs but pass them here
return mCalculatioModel.calculate(params...);
}
}
public class Presenter {
private View mView;
private NfdAdapter mAdapter;
private CalculationModel mModel;
private TokenService mTokenService;
public Presenter(View view, NfdAdapter adapter) {
mView = view;
mNfcAdapter = adapter;
mModel = new CalculationModel();
// or get if from a Service Locator, DI whatever.. if you need to mock the
// TokenService for unittests
mTokenService = new TokenService();
}
public void performCalculation() {
val cmd = CalculationCommand(mAdapter, mTokenService, mModel);
val result = cmd.execute();
mView.setResult(result);
}
public class View {
private Presenter mPresenter;
public View() {
mPresenter = new Presenter(this, NfcAdapter.getDefault(activity);
}
public void onViewCreated() {
mPresenter.performCalculation();
}
public void setResult(Result result) {
// do something with the result
}
}
查看这些资源以获取有关 MVP 及其风格的更多信息:
https://martinfowler.com/eaaDev/uiArchs.html
https://www.martinfowler.com/eaaDev/PassiveScreen.html
https://martinfowler.com/eaaDev/SupervisingPresenter.html