代理模式是通過創建一個代理對象,使用這個代理對象代替實際對象。對於客戶端而言,得到代理對象於操作而言沒有任何影響。
當客戶端操作代理對象時,實際上操作會由實際對象完成。即客戶端操作代理對象,代理對象操作實際對象,而代理對象在操作實際對象時,可以添加額外的操作實現懶加載,權限限定等一系列額外操作。
代理分類:
1、 虛代理:根據需要創建開銷很大的對象,而該對象只有在真正需要的時候纔會被真正創建。實際應用------懶加載。
2、 遠程代理:用來在不同的地址空間表示同一個對象。實際應用------RMI技術
3、 Copy-on-wirte:只有當對象確實改變了,纔會拷貝一個目標對象。
4、 保護代理:控制對原始對象的訪問。
下文則從最簡單的靜態代理開始講解java中的代理模式:
以生活中銷售手機爲例,廠家生產手機,經銷商從廠家拿貨銷售給客戶。而在這個過程中,經銷商就是廠家的代理。可以在廠家銷售過程中增加一系列加價,滿減等活動。而針對客戶,買手機這一操作並沒有因爲是從經銷商處購買收到影響。而經銷商也是在廠家銷售的基礎上增加其他活動,完成整個代理。
1、公用接口
public interface SellProduct {
public int SellPhone(String phoneName);
}
2、實際對象廠家():
public class Producer implements SellProduct{
/**
* 模擬廠家定價
*/
@Override
public int SellPhone(String phoneName) {
// TODO Auto-generated method stub
int price = 0;
switch (phoneName) {
case "iphone":
price = 6000;
break;
case "mi":
price = 2499;
default:
break;
}
System.out.println("銷售手機:"+phoneName+",價格:"+price);
return price;
}
}
3、代理對象(經銷商):
public class Dealer implements SellProduct{
private Producer producer;
public Dealer(Producer producer) {
this.producer = producer;
}
/**
* 經銷商不需要知道廠家如何定價,只要在出廠價基礎上加價即可
*/
@Override
public int SellPhone(String phoneName) {
int price = producer.SellPhone(phoneName)+200;
System.out.println("銷售手機:"+phoneName+",價格:"+price);
return price;
}
}
4、客戶:
public class Client {
public static void main(String []args){
SellProduct sell = new Dealer(new Producer());
sell.SellPhone("iphone");
}
}
運行結果:
銷售手機:iphone,價格:6200
以下介紹兩種其他常用的代理模式:
一:虛代理(實際運用與懶加載):
在數據庫中,往往需要一個對象有很多個屬性,而一次性加載所有屬性是對內存的極大浪費。如果我們第一次只查詢必要的數據,而其他數據等到需要時再查詢,無疑會大大減小內存的消耗。
1、接口:
public interface UserModel {
public int getId();
public void setId(int id);
public String getName();
public void setName(String name);
}
2、實際對象:
public class UserModelImpl implements UserModel {
private int id;
private String name;
@Override
public int getId() {
// TODO Auto-generated method stub
return id;
}
@Override
public void setId(int id) {
// TODO Auto-generated method stub
this.id = id;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
}
public class ProxyModel implements UserModel{
private UserModelImpl userModel;
private boolean isLoad = false;
public ProxyModel(UserModelImpl userModel){
this.userModel = userModel;
}
@Override
public int getId() {
// TODO Auto-generated method stub
return userModel.getId();
}
@Override
public void setId(int id) {
// TODO Auto-generated method stub
userModel.setId(id);
}
@Override
public String getName() {
// TODO Auto-generated method stub
if(!this.isLoad){
reload();
this.isLoad = true;
}
return userModel.getName();
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
userModel.setName(name);
}
/**
* 重新從數據庫中獲取name注入實際對象
*/
private void reload(){
String name = getNameFromSQL();
System.out.println("重新從數據庫加載數據");
userModel.setName(name);
}
/**
* 模擬從數據庫獲取name操作
* @return
*/
private String getNameFromSQL(){
return "simulation";
}
}
4、客戶使用:
public class Client {
/**
* 模擬從數據庫中查詢,因爲不需要知道其他屬性,只注入id即可
* @param usermodel
*/
private static void SQLQuery(UserModel usermodel){
usermodel.setId(1);
}
public static void main(String []args){
ProxyModel proxy = new ProxyModel(new UserModelImpl());
SQLQuery(proxy);
System.out.println("id:"+proxy.getId());
System.out.println("name:"+proxy.getName());
}
}
運行結果:
id:1
重新從數據庫加載數據
simulation
二 保護代理:
控制原始對象訪問的代理。
1、接口:
public interface OAOperate {
public void add();
public void select();
public void delete();
}
2、原始對象:
public class OAOperater implements OAOperate{
private String name;
private int flag;
public OAOperater(String name,int flag) {
this.name = name;
this.flag = flag;
}
public int getFlag(){
return this.flag;
}
@Override
public void add() {
//省略相應操作
}
@Override
public void select() {
//省略相應操作
}
/**
* delete需要權限設置
*/
@Override
public void delete() {
//省略相應操作
System.out.println("刪除操作");
}
}
3、代理對象:
public class OAProxy implements OAOperate {
private OAOperater operate;
public OAProxy(OAOperater operate) {
this.operate = operate;
}
@Override
public void add() {
// TODO Auto-generated method stub
}
@Override
public void select() {
// TODO Auto-generated method stub
}
@Override
public void delete() {
// TODO Auto-generated method stub
if (operate.getFlag() != 4) {
System.out.println("權限不足,不能修改");
} else {
operate.delete();
}
}
}
4、客戶:
public class Client {
public static void main(String []args){
OAOperate operate = new OAProxy(new OAOperater("xiaoming", 3));
operate.delete();
OAOperate operater = new OAProxy(new OAOperater("paditang", 4));
operater.delete();
}
}
運行結果:
權限不足,不能修改
刪除操作