問題引出
當客戶端需要獲取一個訂單(Order)的信息,假設一個訂單由客戶名、商品名和數量構成,那麼客戶端需要與服務端交互三次,依次取得這些信息
這樣設計是一種可行的方案,但存在兩個嚴重的問題(出大問題 )
-
對於獲取一個訂單而言,這種操作模式過於繁瑣,且不具備較好的可維護性
-
前後累計進行了三次客戶端與服務端的通訊,性能成本較高
解決方法:Value Object(值對象)模式
Value Object 模式提倡將一個對象的各個屬性進行封裝,將封裝後的對象在網絡中傳遞,從而使系統擁有更好的交互模型,並且減少網絡通信數據,從而提高系統性能。
// RMI服務端接口
public interface IOrderManager extends Remote {
public Order getOrder(int id) throws RemoteException;
public String getClientName(int id) throws RemoteException;
public String getProdName(int id) throws RemoteException;
public int getNumber(int id) throws RemoteException;
}
// 作爲Value Object 的 Order 對象
public class Order implements Serializable {
private int orderId;
private String clientName;
private int number;
private String productName;
public int getOrderId() {
return orderId;
}
public void setOrderId(int orderId) {
this.orderId = orderId;
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
}
// 實現IOrderManager,返回數據(本來應該和數據庫進行交互的,但爲了方便直接返回確定值)
public class OrderManager extends UnicastRemoteObject implements IOrderManager {
protected OrderManager() throws RemoteException {
super();
}
private static final long serialVersionUID = -171703007581295639L;
@Override
public Order getOrder(int id) throws RemoteException {
Order o = new Order();
o.setClientName("TuoJun");
o.setNumber(20);
o.setProductName("rice");
return o;
}
@Override
public String getClientName(int id) throws RemoteException {
return "TuoJun";
}
@Override
public String getProdName(int id) throws RemoteException {
return "rice";
}
@Override
public int getNumber(int id) throws RemoteException {
return 20;
}
}
// 業務邏輯層,註冊並開啓RMI服務器
public class OrderManagerServer {
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(1099); // 註冊RMI端口
IOrderManager userManager = new OrderManager(); // RMI遠程對象
Naming.rebind("OrderManager", userManager); // 綁定RMI對象
System.out.println("OrderManager is ready");
}catch (Exception e){
System.out.println("OrderManager Server failded:" + e);
}
}
}
// 客戶端的測試代碼,分別展示了使用Value Object 模式封裝數據和不使用Value Object 模式的性能差異
public class OrderClient {
public static void main(String[] args) {
try {
IOrderManager userManager = (IOrderManager) Naming.lookup("OrderManager");
long begin = System.currentTimeMillis();
for (int i =0; i < 100; i++){
// 使用Value Object 模式封裝數據
userManager.getOrder(i);
}
System.out.println("Value Object模式花費的時間:" + (System.currentTimeMillis() - begin));
begin = System.currentTimeMillis();
for (int i =0; i < 100; i++){
// 不使用Value Object 模式封裝數據
userManager.getClientName(i);
userManager.getNumber(i);
userManager.getProdName(i);
}
System.out.println("傳統模式花費的時間:" + (System.currentTimeMillis() - begin));
}catch (Exception e){
System.out.println("OrderManager Server failded:" + e);
}
}
}
// 運行結果
// OrderManagerServer 服務端
OrderManager is ready
// OrderClient 客戶端
Value Object模式花費的時間:85
傳統模式花費的時間:106
由此可見,對傳輸數據進行有效的封裝,可以明顯提升遠程方法調用的性能
分析
在基於Value Object 模式的結構中,爲了獲取一份訂單信息,只需要進行一次網絡通信,縮短了數據存取的時響應時間,減少了網絡數據流量,提高了性能,也能使系統接口具有更好的可維護性