目前,我正在进行我的学术研究,我通过尽可能实现四人组设计模式来设计一个 Android 应用程序(注意:GoF 模式是必须的,它是我进行的研究的一部分)。
现在我来到了通过 Repository 从远程/Rest API 获取数据的部分。我不希望应用程序总是从远程获取完全相同的数据,因为这非常昂贵(消耗时间、资源、带宽等),就像大多数应用程序一样,我决定添加缓存机制。
在我之前的 android 应用程序项目中,我通常使用数据库 (Room) 结合专用字段“缓存”数据,以保持缓存对象保留在内存中(参见下面的代码 fragment )。
但是,我几乎没有时间(由于研究截止日期),我想更多地关注 GoF 在我设计的应用程序上的实现,并且更愿意避免与数据库相关的东西。
下面的代码是我的 Repository 类的 fragment 。当我(比方说一个 ViewModel)需要用户数据时,它将调用存储库中的 getUser(
) 方法。
在 getUser()
方法中,我将检查 shouldRefresh 是否为 false 以及缓存对象是否为空。一旦为真,它将返回 cacheUser
,但如果为假,则将调用 fetchUser()
方法(改造库提供的接口(interface))。我会认为 fetchUser() 执行一项非常繁重且昂贵的任务(因为它需要互联网并且该过程取决于网络质量)。
Repository.java
类的 fragment 。
public class AccountRepository {
private AccountWebservice webservice;
private User cacheUser;
public User getUser(String accessToken, int userId, boolean shouldRefresh) {
if (!shouldRefresh && cacheUser != null) {
return cacheUser;
}
Call<SinglePayloadResponse<User>> call = webservice.fetchUser(accessToken, userId);
call.enqueue(new Callback<SinglePayloadResponse<User>>() {
@Override
public void onResponse(Call<SinglePayloadResponse<User>> call, Response<SinglePayloadResponse<User>> response) {
assert response.body() != null;
cacheUser = response.body().getPayload(); // currently I'm *caching* the response by assign it to cacheUser
return cacheUser;
}
@Override
public void onFailure(Call<SinglePayloadResponse<User>> call, Throwable t) {
}
});
}
}
我发现代理模式(Smart Proxy Pattern)用于处理昂贵对象的创建,如本例(Usage of Proxy design pattern)所示,正如我们所见,引入了 ProxyImage 来包装真正的昂贵对象(RealImage ) 如果已经加载则不再重新加载。
我看到智能代理模式具有我希望在此应用程序中完成的行为(如缓存)。我想知道我是否可以实现此模式以从 Repository 类中的 Web 服务缓存响应(如用户数据、最近查看的产品、最近的搜索结果和其他需要尽快访问的相关内容)。
现在是真正的问题:
我的情况是否足够合理以应用智能代理模式?如果可以,如何应用? (让我们以上面的存储库类的 fragment 为例,这是我目前访问用户数据的解决方案,我需要应用智能代理模式)
我还是努力去学习GoF模式的23个目录,由于时间有限,知识有限,视角有限,很容易漏掉一些关于模式的东西,甚至是重要的东西。因此,感谢任何对“我的”或“您的”误解的回答、建议和澄清,谢谢。
最佳答案
要使用代理,您首先需要创建一个接口(interface)。由于您已经使用了名称“AccountRepository”,因此我将调用接口(interface)“IAccountRepository
public interface IAccountRepository {
User getUser(String accessToken, int userId, boolean shouldRefresh);
}
然后让 AccountRepository 实现 IAccountRepository 并从那里移出所有与缓存相关的逻辑:
public class AccountRepository implements IAccountRepository {
private AccountWebservice webservice;
public User getUser(String accessToken, int userId, boolean shouldRefresh) {
Call<SinglePayloadResponse<User>> call = webservice.fetchUser(accessToken, userId);
call.enqueue(new Callback<SinglePayloadResponse<User>>() {
@Override
public void onResponse(Call<SinglePayloadResponse<User>> call, Response<SinglePayloadResponse<User>> response) {
assert response.body() != null;
cacheUser = response.body().getPayload(); // currently I'm *caching* the response by assign it to cacheUser
return cacheUser;
}
@Override
public void onFailure(Call<SinglePayloadResponse<User>> call, Throwable t) {
}
});
}
}
现在你可以实现你的代理了:
public AccountRepositoryCacheProxy implements IAccountRepository {
private IAccountRepository accountRepository
public User getUser(String accessToken, int userId, boolean shouldRefresh) {
if (!userIsInCache(userId) || shouldRefresh) {
User result = accountRepository.GetUser(accessToken, userId, false);
addUserInCache(userId, result);
return result;
}
return userFromCache(userid);
}
}
您的实际缓存应该类似于 String、User 的并发字典。
在您的代码中任何需要帐户存储库的地方,您都需要以这种方式创建它:
IAccountRepository accountRepository = new AccountRepositoryCacheProxy( new AccountRepository()));
实际上依赖注入(inject)系统会好得多。
关于android - 如何使用(智能引用)代理设计模式实现缓存机制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62847149/