1.门面模式简介
1.1 简介
为子系统中的一组接口提供一个统一的接口
即:在隐藏子系统复杂性的同时,门面模式又通过一个易于使用的接口提供子系统的全部功能。
例如:一个洗衣机有两种功能,强力洗涤和轻度洗涤,用户使用只需做出两种洗涤的决定,无需考虑两种洗涤的流程
1.2门面模式的适用情况
- 为遗留的后端系统提供简单且统一的访问
- 为类创建一个公开的API,如驱动程序
- 为可用服务提供粗粒度的访问。服务会被组合
- 减少网路调用。门面会对子系统发起多次调用,而远程客户端只对门面进行一个调用
- 将应用的流程与内部细节封装起来,从而提升安全性并简化操作
2.普通代码实现门面模式
类比于洗衣机的功能
public class WashingMachine(){
public void heavilySoiled(){
setWaterTemperature(100);
.....
StartWash();
}
public void lightSoiled(){
setWaterTemperature(40);
.....
StartWash();
}
}
3.Java EE 实现门面模式
知识补充:
有状态对象(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
无状态对象(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。
3.1使用无状态Bean实现门面
@Stateless
介绍:有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象.不能保存数据,是不变类,是线程安全的。
(可参考:https://blog.youkuaiyun.com/QQ578473688/article/details/79158446)的文章
下面是三段构成门面子系统的EJB代码
package com.devchronicles.facade;
import javax.ejb.Stateless;
@Stateless
public class CustomerService {
public long getCustomer(int sessionID) {
// get logged in customer id
return 100005L;
}
public boolean checkId(long x) {
// check if customer id is valid
return true;
}
}
package com.devchronicles.facade;
import javax.ejb.Stateless;
@Stateless
public class LoanService {
public boolean checkCreditRating(long id, double amount) {
// check if customer is eligible for the amount
return true;
}
}
package com.devchronicles.facade;
import javax.ejb.Stateless;
@Stateless
public class AccountService {
public boolean getLoan(double amount) {
// check if bank vault has enough
return true;
}
public boolean setCustomerBalance(long id, double amount) {
// set new customer balance
return true;
}
}
无状态门面的实现
package com.devchronicles.facade;
import javax.ejb.Stateless;
import javax.inject.Inject;
@Stateless
public class BankServiceFacade {
@Inject
CustomerService customerService;
@Inject
LoanService loanService;
@Inject
AccountService accountService;
public boolean getLoan(int sessionId, double amount) {
boolean result = false;
long id = customerService.getCustomer(sessionId);
if (customerService.checkId(id)) {
if (loanService.checkCreditRating(id, amount)) {
if (accountService.getLoan(amount)) {
result = accountService.setCustomerBalance(id, amount);
}
}
}
return result;
}
}
一个门面可以调用其它子系统的门面,这反过来又会封装它们自己的逻辑与流程。
关于@inject可以参考:
(https://blog.youkuaiyun.com/qq_36838191/article/details/81297027?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7Eessearch%7Evector-11.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7Eessearch%7Evector-11.no_search_link)
3.2总结
在实现会话门面的时候,要确定用例是否需要维持状态。只调用门面的一个方法来接收所需的服务是非对话式的,因此没必要在方法调用间保持会话状态。应该将这种门面实现为无状态会话bean.