1. 什麼是代理模式?
官方定義是:為其他對象提供一種代理以控制對這個對象的通路。其實說白了讓代理做你原來要做的事情。
2. 代理案例
舉個例子,我們正常玩遊戲,需要個人登入遊戲賬号,然後進行更新,這是一件漫長而又艱辛的事情,我們無法開外挂,因為要封号,于是我們找到代理廠家,溝通後代理商登入你的遊戲賬号進行更新,這就是代理
3. 靜态代理
建立一個接口,然後建立被代理的類實作該接口并且實作該接口中的抽象方法。之後再建立一個代理類,同時使其也實作這個接口。在代理類中持有一個被代理對象的引用,而後在代理類方法中調用該對象的方法。
如圖:
開始撸代碼:
3.1 定義一個IGamePlayer接口
public interface IGamePlayer {
// 登入遊戲
void login(String user, String password);
// 打怪
void killBoss();
}
3.2 定義一個玩家類
public class GamePlayer implements IGamePlayer {
private String name = "";
public GamePlayer(String _name) {
this.name = _name;
}
@Override
public void login(String user, String password) {
System.out.println("登入名為" + user + "的使用者"+ this.name + "登入成功");
}
@Override
public void killBoss() {
System.out.println(this.name + "打boss");
}
}
3.3 定義一個代理類GamePlayerProxy
public class GamePlayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer = null;
public GamePlayerProxy(IGamePlayer _gamePlayer) {
this.gamePlayer = _gamePlayer;
}
@Override
public void login(String user, String password) {
this.gamePlayer.login(user, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
}
3.4 代理上玩家的号進行代練,定義一個Client進行測試
public class Client {
public static void main(String[] args) {
// 定義一個玩家
IGamePlayer player = new GamePlayer("張三");
// 定義一個代練,代練玩家的号
GamePlayerProxy proxy = new GamePlayerProxy(player);
proxy.login("zhangsan", "123");
proxy.killBoss();
}
}
4. 代理模式的擴充:普通代理和強制代理。
我們平時會聽到代理分為和
透明代理
普通代理
,
透明代理
:使用者不用設定代理伺服器位址直接通路,即代理伺服器對使用者來說是透明的,使用者不知道它的存在
:普通代理和強制代理屬于一類,普通代理使用者必須知道代理的存在才能進行通路,即代理伺服器對使用者來說是不透明的。強制代理則調用者直接調用真實角色,不關心代理存在,代理的産生由真實角色決定。
普通代理
4.1 普通代理:
結構如圖,對上述結構做小部分修改。
4.1.1 接口不用變化,修改GamePlayer
public class GamePlayer implements IGamePlayer {
private String name = "";
// 變動地方
public GamePlayer(IGamePlayer _gamePlayer, String _name) throws Exception {
if (_gamePlayer == null) throw new Exception("無法建立真實角色");
else this.name = _name;
}
@Override
public void login(String user, String password) {
System.out.println("登入名為" + user + "的使用者"+ this.name + "登入成功");
}
@Override
public void killBoss() {
System.out.println(this.name + "打boss");
}
}
4.1.2 修改代理類
public class GamePlayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer = null;
public GamePlayerProxy(String _name) {
try {
gamePlayer = new GamePlayer(this, _name);
}catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void login(String user, String password) {
this.gamePlayer.login(user, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
}
4.1.3 修改測試類
public class Client {
public static void main(String[] args) {
// 建立一個代理對象
IGamePlayer proxy = new GamePlayerProxy("張三");
// 代理對象對賬号進行代理更新
proxy.login("zhangsan", "123");
proxy.killBoss();
}
}
運作結果完全相同,在該模式下,調用者隻知道代理而不用知道真實的角色是誰,真正的主角修改靈活,對高層子產品沒有什麼影響,該模式适合擴充性好的場合。
4.1 強制代理:
一般都是通過代理找到真實的角色,但是強制代理卻是通過真實的角色找到代理角色,否則不能通路。
舉個例子
:你有事情通過找到明星A去通路他的導演朋友,而不想直接找他的經紀人B去找,但是撥通A電話後A說太忙了,你去找他的經紀人
對上述圖結構進行修改
4.1.1 修改接口
public interface IGamePlayer {
// 登入遊戲
void login(String user, String password);
// 打怪
void killBoss();
// 每個人都可以找到自己的代理
IGamePlayer getProxy();
}
4.1.2修改強制代理的真實角色GamePlayer
public class GamePlayer implements IGamePlayer {
private String name = "";
private IGamePlayer proxy = null;
public GamePlayer(String _name) {
this.name = _name;
}
@Override
public void login(String user, String password) {
if (this.isProxy()) {
System.out.println("登入名為" + user + "的使用者" + this.name + "登入成功");
}else {
System.out.println("請使用指定代理通路");
}
}
@Override
public void killBoss() {
if (this.isProxy()) {
System.out.println(this.name + "打boss");
}else {
System.out.println("請使用指定代理通路");
}
}
@Override
public IGamePlayer getProxy() {
this.proxy = new GamePlayerProxy(this);
return this.proxy;
}
// 檢驗是否代理通路
private boolean isProxy() {
if (this.proxy == null) {
return false;
} else {
return true;
}
}
}
4.1.3 修改強制代理的代理類
public class GamePlayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer = null;
public GamePlayerProxy(IGamePlayer _gamePlayer) {
this.gamePlayer = _gamePlayer;
}
@Override
public void login(String user, String password) {
this.gamePlayer.login(user, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
@Override
public IGamePlayer getProxy() {
return this;
}
}
4.1.4 修改測試類Client
public class Client {
public static void main(String[] args) {
// 1直接通路真實角色
IGamePlayer player = new GamePlayer("張三");
player.login("zhangsan", "123"); // 輸出:請使用指定代理通路
player.killBoss();// 輸出:請使用指定代理通路
// 2.直接通路代理類
IGamePlayer player1 = new GamePlayer("張三");
IGamePlayer proxy1 = new GamePlayerProxy(player1);
proxy1.login("zhangsan", "123");// 輸出:請使用指定代理通路
proxy1.killBoss();// 輸出:請使用指定代理通路
// 3.使用強制代理通路,即找到明确的代理
IGamePlayer player2 = new GamePlayer("張三");
IGamePlayer proxy2 = player2.getProxy();
proxy2.login("zhangsan", "123"); // 輸出:登入名為zhangsan的使用者張三登入成功
proxy2.killBoss(); // 輸出:張三打boss
}
}