**英文名稱:Proxy Pattern**
**定義**:為其他對象提供一種代理以控制對這個對象的訪問。
**我的理解**:代理模式相當于現實生活中的明星經紀人,提供了一個很好的訪問控制。
**代理模式的分類:**
靜態代理模式
--|普通代理模式
--|強制代理模式
動態代理模式
## 代理模式的一般模式:
###Subject抽象主題角色
--|抽象主題類可以是抽象類也可以是接口,是一個最普通的業務型定義,無特殊要求。
### RealSubject具體主題角色
--|也被叫做委托角色、被代理角色。是業務邏輯的具體執行者
### Proxy代理主題角色
--|也叫作代理類、委托類。負責對真實角色的應用,把所有抽象主題類定義的方法限制委托給真實角色實現, 并且在真實主題角色處理完畢后做預處理和善后處理工作。
~~~
public class ProxyTest {
public static void main(String[] args) {
//實例化一個真實的被委托類。
System.out.println("---------實例化一個真實的被委托類--------------");
Proxy realSubject = new Proxy(new RealSubject());
realSubject.request();
}
}
interface Subject{
//定義一個方法,讓子類去實現
public void request();
}
class RealSubject implements Subject{
//被委托角色,執行具體是方法實現
@Override
public void request() {
System.out.println("我是RealSubject,我在執行方法....");
}
}
class Proxy implements Subject{
//代理類,負責真實角色的應用。
private Subject subject = null;
//設置想要的被代理者
public Proxy(Subject subject){
this.subject = subject;
}
@Override
public void request() {
before();
this.subject.request();
after();
}
private void before(){
System.out.println("代理類,在做事前處理...");
}
private void after(){
System.out.println("代理類,在做善后處理...");
}
}
~~~
##普通代理模式:
--|要求客戶端只能訪問代理角色,而不能訪問真實角色。
一個例子:
一款非常著名的游戲,游戲玩家需要整天的登錄、打怪、升級。但是游戲玩家沒有時間, 所以他需要找一個代理來替他完成這個重復的過程,并使得游戲技能提升。
--|IGamePlayer游戲玩家接口,定義login(String name,String password)
??? killBoss()、upGrade()
--|GamePlayer 游戲玩家,真正的被委托類,實現這些游戲方法。
--|GameProxy 游戲代理,通過代理設置,去委托真實類實現需要的方法。

~~~
public class CommonProxy {
public static void main(String[] args) {
String name = "xy";
GameProxy proxy = new GameProxy(name);
proxy.login(name, "Ilovelzl");
proxy.killBoss();
proxy.upGrade();
System.out.println("-----代理時間到--------");
}
}
interface IGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
}
class GameProxy implements IGamePlayer{
private GamePlayer gamePlayer = null;
//通過構造函數來傳遞要對誰進行游戲代理
public GameProxy(String name) {
try {
this.gamePlayer = new GamePlayer(this, name);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void login(String name, String password) {
this.gamePlayer.login(name, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
@Override
public void upGrade() {
this.gamePlayer.upGrade();
}
}
class GamePlayer implements IGamePlayer{
private String name="";
//設置一個提供代理類的構造函數,限制用戶必須通過代理類來實例化對象。
public GamePlayer(IGamePlayer iGamePlayer,String name)throws Exception {
if(iGamePlayer == null){
throw new Exception("不能創建角色");
}else{
this.name = name;
}
}
@Override
public void login(String name, String password) {
System.out.println("用戶:"+this.name+"登錄成功!");
}
@Override
public void killBoss() {
System.out.println(this.name+"在打怪!");
}
@Override
public void upGrade() {
System.out.println(this.name+"又升了一級...");
}
}
~~~
### 強制代理
---|必須通過真實角色找到代理角色,否則不能訪問。
依舊是打怪的例子實現;
~~~
public class CommonProxy {
public static void main(String[] args) {
//首先創建一個游戲玩家
System.out.println("------只創建一個玩家,不設置代理的效果---------");
GamePlayer xy = new GamePlayer("xy");
xy.login("xy", "pass");
xy.killBoss();
xy.upGrade();
System.out.println("------創建一個玩家,并設置代理的效果---------");
GameProxy proxy = (GameProxy) xy.getProxy();
proxy.login("xy", "pass");
proxy.killBoss();
proxy.upGrade();
}
}
interface IGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
IGamePlayer getProxy();
}
class GameProxy implements IGamePlayer{
private IGamePlayer gamePlayer = null;
//通過構造函數來傳遞要對誰進行游戲代理
public GameProxy(IGamePlayer gamePlayer) {
this.gamePlayer = gamePlayer;
}
@Override
public void login(String name, String password) {
this.gamePlayer.login(name, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
@Override
public void upGrade() {
this.gamePlayer.upGrade();
}
//設置代理,代理沒有具體的實例,因此暫時返回自己。
@Override
public IGamePlayer getProxy() {
// TODO Auto-generated method stub
return this;
}
}
class GamePlayer implements IGamePlayer{
private String name="";
private IGamePlayer proxy = null;
//設置一個提供代理類的構造函數,限制用戶必須通過代理類來實例化對象。
public GamePlayer(String name) {
this.name = name;
}
//設置代理
@Override
public IGamePlayer getProxy() {
this.proxy = new GameProxy(this);
return this.proxy;
}
@Override
public void login(String name, String password) {
if(this.isProxy()){
System.out.println("用戶:"+this.name+"登錄成功!");
}
else{
System.out.println("請使用指定的代理訪問...");
}
}
@Override
public void killBoss() {
if(this.isProxy()){
System.out.println(this.name+"在打怪!");
}
else{
System.out.println("請使用指定的代理訪問...");
}
}
@Override
public void upGrade() {
if(this.isProxy()){
System.out.println(this.name+"又升了一級!");
}
else{
System.out.println("請使用指定的代理訪問...");
}
}
private boolean isProxy(){
if( proxy == null){
return false;
}
return true;
}
}
~~~
### 動態代理

~~~
public class DynamicProxy {
public static void main(String[] args) {
//定義一個游戲玩家
MyIGamePlayer player = new MyGamePlayer("lzl");
//定義一個handler
InvocationHandler handler = new GamePlayIH(player);
//開始游戲,獲得類的classLoader
ClassLoader cl = player.getClass().getClassLoader();
//動態產生一個代理者
MyIGamePlayer proxy = (MyIGamePlayer)Proxy.newProxyInstance(cl,new Class[]{MyIGamePlayer.class},
handler);
proxy.login("lzl", "123");
proxy.killBoss();
proxy.upGrade();
}
}
interface MyIGamePlayer{
void login(String name,String password);
void killBoss();
void upGrade();
}
class GamePlayIH implements InvocationHandler{
//設置動態代理,必須繼承InvocationHandler接口。并實現invoker方法
//被代理者
Class cls = null;
Object obj = null;
public GamePlayIH(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = method.invoke(this.obj, args);
if(method.getName().equalsIgnoreCase("killBoss")){
System.out.println("有人用我的賬號登錄...");
}
return result;
}
}
class MyGamePlayer implements MyIGamePlayer{
private String name="";
//設置一個提供代理類的構造函數,限制用戶必須通過代理類來實例化對象。
public MyGamePlayer(String name){
this.name = name;
}
@Override
public void login(String name, String password) {
System.out.println("用戶:"+this.name+"登錄成功!");
}
@Override
public void killBoss() {
System.out.println(this.name+"在打怪!");
}
@Override
public void upGrade() {
System.out.println(this.name+"又升了一級...");
}
}
~~~
**動態代理的一般模式**:
AOP:面向橫切面編程。
動態代理實現代理的職責,業務邏輯ISubject實現相關的邏輯給你。
兩者時間沒有必然的相互耦合關系。
通知Advice從另一個切面切入,最終在高層模塊也是ProxyT進行耦合,完成邏輯的封裝任務。

~~~
public class ProxyT {
public static void main(String[] args) {
/*//定義一個主題
ISubject sub = new MySubject();
//定義主題代理
ISubject proxy = SubjectDynamicProxy.newProxyInstance(sub);
proxy.doSomething();*/
}
}
interface ISubject{
void doSomething();
}
class MySubject implements ISubject{
@Override
public void doSomething() {
System.out.println("子類具體實現方法...");
}
}
interface Advice{
void someAdvice();
}
class MyAdvice implements Advice{
//該類用于說明,在
@Override
public void someAdvice() {
System.out.println("一些前言方法...");
}
}
/**
* 動態代理的Handler類
* @author admin
*
*/
class MyInvocation implements InvocationHandler{
Object obj = null;
public MyInvocation(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return method.invoke(obj, args);
}
}
class SubjectDynamicProxy{
public static <T> T newProxyInstance(ISubject subject){
//獲取類加載器
ClassLoader loader = subject.getClass().getClassLoader();
//獲得接口數組
Class<?>[] interfaces = subject.getClass().getInterfaces();
//獲得handler
InvocationHandler handler = new MyInvocation(subject);
return (T)Proxy.newProxyInstance(loader, interfaces, handler);
}
}
~~~
也可以將上面的改為SubjectDynamicProxy改為DynamicProxys。
~~~
class DynamicProxys{
@SuppressWarnings("unchecked")
public static <T> T newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,InvocationHandler handler ){
if(true){
//執行一個前置通知..
new MyAdvice().someAdvice();
}
return (T)Proxy.newProxyInstance(loader, interfaces, handler);
}
~~~
- 前言
- 6大設計原則(一)---單一職責原則
- 6大設計原則(二)---里氏替換原則
- 6大設計原則(三)---依賴倒置原則
- 6大設計模式(四)----接口隔離原則
- 6大設計原則(五)---迪米特法則
- 6大設計原則(六)---開閉原則。
- 設計模式(一)---單例模式
- 設計模式(二)---工廠方法模式
- 設計模式(三)---抽象工廠模式
- 設計模式(四)---模板方法模式
- 設計模式(五)---建造者模式
- 設計模式(六)---代理模式
- 設計模式(七)---原型模式
- 設計模式(八)---中介者模式
- 設計模式(九)---命令模式
- 設計模式(十)---責任鏈模式
- 設計模式(十一)---裝飾模式
- 設計模式(十二)---策略模式
- 設計模式(十三)---適配器模式
- 設計模式(十四)---迭代器模式
- 設計模式(十五)---組合模式
- 設計模式(十六)---觀察者模式
- 設計模式(十七)---門面模式
- 設計模式(十八)---備忘錄模式
- 設計模式(十八)---訪問者模式
- 設計模式(二十)---狀態模式
- 設計模式(二十二)---享元模式
- 設計模式(二十三)---橋梁模式