1. 程式人生 > 實用技巧 >Java設計模式之004--代理模式

Java設計模式之004--代理模式

代理模式(Proxy : 為其他物件提供一種代理以控制對這個物件的訪問。
代理模式說白了就是“真實物件” 的代表, 在訪問物件時引入一定程度的間接性, 因為這種間接性可以附加多種用途。

舉例說明:操作員查詢銷售訂單功能, 為了提高查詢效能, 我們接入快取功能, 如果快取中有資料, 那麼直接返回快取中的資料,;如果快取中沒有資料, 那麼查詢訂單資料後, 把資料加入到快取, 這樣在下次查詢訂單資料時, 就可以從快取中讀取了。

a.建立訂單類、模擬的資料庫類、模擬的快取類;

//模擬的資料庫類:提供getOrder方法來通過oid查詢訂單資訊
public class DB {
private static List<Order> list = new ArrayList<>();
static{
list.add(new Order(1,"毛巾3條",45,"2020-2-1"));
list.add(new Order(2,"小紙巾10包",12,"2020-1-21"));
list.add(new Order(3,"洗髮水1瓶",32,"2020-1-30"));
list.add(new Order(4,"紅牛1箱",36,"2020-2-2"));
list.add(new Order(5,"哈脾2箱",120,"2020-2-3"));
}

public Order getOrder(int oid){
System.out.println("從資料庫中查詢資料...");
for(Order order:list){
if(order.getOid() == oid){
return order;
}
}
return null;
}
}

//模擬的快取類:提供getCache方法來通過oid查詢訂單資訊; 提供putCache方法將訂單資訊存放到快取中;
public class Cache {
    private Map<Integer,Order> map = new HashMap();
private volatile static Cache cache;

private Cache(){
}

//雙檢 + 單例模式
public static Cache getInstance(){
if (cache == null){
synchronized (Cache.class){
if (cache == null){
cache = new Cache();
}
}
}
return cache;
}

//把訂單新增到快取中
public void putCache(int key, Order value){
System.out.println("把訂單資料新增到快取中...");
map.put(key,value);
}

//從快取中獲取訂單
public Order getCache(int key){
System.out.println("從快取中查詢訂單資料...");
return map.get(key);
}
}

b.定義業務類(被代理的物件類)介面,以供業務類和代理類去實現

public interface OrderDao {
public Order queryOrder(int oid);
}

c.定義業務類、代理類實現業務類(被代理的物件類)介面

public class OrderDaoImpl implements OrderDao {
@Override
public Order queryOrder(int oid) {
DB db = new DB();
Order order = db.getOrder(oid);
return order;
}
}

public class OrderProxy implements OrderDao {
private OrderDao target; //目標物件(被代理的物件)

public OrderProxy (OrderDao target){
this.target = target;
}


@Override
public Order queryOrder(int oid) {
Cache cache = Cache.getInstance();
Order order = cache.getCache(oid); //從快取中查訂單(代理做了被代理物件額外的業務)
if (null == order){
order = target.queryOrder(oid); //從資料庫中查訂單(被代理物件的業務,方法名相同)
cache.putCache(order.getOid(),order); //把訂單放入快取中
}
return order;
}
}

測試對比:

public class Test {
public static void main(String[] args) {
OrderDaoImpl odi = new OrderDaoImpl();
Order order = odi.queryOrder(2); //實際呼叫的是db.getOrder(oid)
System.out.println(order);
System.out.println("-------------------");
//查快取
OrderProxy orderProxy = new OrderProxy(odi);
Order order1 = orderProxy.queryOrder(2);
System.out.println(order1);
System.out.println("----------第二次查詢---------");
Order order2 = orderProxy.queryOrder(2);
System.out.println(order2);
}
}