`
king_tt
  • 浏览: 2250397 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

【设计模式】学习笔记15:代理模式(Proxy Pattern)

 
阅读更多



本文出自 http://blog.csdn.net/shuangde800



本笔记内容:
1. JAVA远程代理调用(RMI)
2. 代理模式



走进代理模式

在上一篇的状态模式中,我们实现了一个糖果机GumballMachine, 客户通过投币可以买到糖果.


现在设想这样一种情况: 糖果机是属于某个糖果公司的,这个公司的CEO坐在办公室里喝茶,看报纸, 但他还想要随时了解糖果机的状态,

比如还剩下多少个糖果,卖了多少钱等等. CEO要怎样才能远程"遥控"糖果机获取信息呢?

这就得用到代理模式(Proxy Pattern)了.


可能我们会想到通过socket网络连接, 自己定义好协议去控制糖果机.这个其实就是代理模式的底层实现.


所谓代理(Proxy)就是代表某个真实的对象, 这个"代理"可以看作是真正的对象, 比如CEO在办公室中拿到了糖果机的"代理", 然后CEO

对"代理"进行的任何操作,到会"传送"到远程真实的糖果机上, 然后糖果机就会作出反应, 看起来好像"代理"就是真正的糖果机一样.

这一切的动作是利用网络和真正对象沟通的.



远程代理的角色

远程代理就好比"远程对象的本地代表".

何谓"远程对象"? 这是一种对象,活在不同的Java虚拟机(JVM)堆中(更一般的说法,在不同的地址空间运行的远程对象).

何谓"本地代表"? 这是一种可以由本地方法调用的对象,其行为会转发到远程对象中.




你的客户对象所做的就像是在做远程方法调用, 但其实只是调用本地堆中的"代理对象"上的方法,

再由代理处理所有网络通信的底层细节




JAVA远程方法调用(RMI)

如果要自己手动去实现网络通信的底层, 那么显然会大大加大编程复杂度, 幸运的是, Java中已经有内置工具给我们使用了.

这就是:Java远程方法调用(RMI: Remote Mehod Invocation)


用Java RMI创建远程服务的基本步骤:

1. 创建远程接口

// 这个接口扩展自Remote,支持远程调用
public interface MyRemote extends Remote{
    // 每次远程调用都是“有风险的”,因为会设计网络和I/O
    // 所以这个接口的方法都要声明异常
    // 还要确定方法的返回值是primitive类型或者可序列化(Serializable)类型
    // 远程方法的变量会被打包并通过网络运送,这要靠序列化来完成
    // 自定义的类必须序列化
    public String sayHello() throws RemoteException;
}


2. 实现远程接口

public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote{

      // 声明默认构造器
     protected MyRemoteImpl() throws RemoteException {
        super();
    }
    
    // 实现接口
    public String sayHello() throws RemoteException {
        return "Hello, world!";
    }

    public static void main(String[] args) {
        
        try {
            MyRemote service = new MyRemoteImpl();
            // 用Naming.rebind()绑定到remiregistry 
            Naming.rebind("rmi://127.0.0.1/RemoteHello", service);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}


3. 命令行编译上面两个类(PS. 用的是Ubuntu系统,不是用IDE写的,所以两个类也没有package,放在同一个目录下。实际上,如果直接用IDE编译会遇到一个问题,后面会提)

这样就把Remote.java 和RemoteImpl.java两个类都编译了,编译完后,产生两个编译文件:


MyRemote.class和MyRemoteImpl.java


4. 用rmic产生stub和skeleton

rmic是JDK内的一个工具,用来为一个服务类产生stub和skeleton。命名习惯是在远程实现的名字后面加上_Stub或_Skel。rmic有一些选项可以调整,包括不要产生skeleton,查看源代码,甚至使用IIOP作为协议。这个例子使用的是rmic常见的方式,将类产生在当前目录下(就是cd到的目录)。注意,rmic必须看到你的实现类,所以你可能会从你的远程实现所在的目录下执行rmic


执行完之后,发现目录下多了一个名为MyRemote_Stub.class的文件:




5. 执行rmiregistry

开启一个终端,启动rmiregistry


注意这个终端不要关闭!


6. 启动服务端服务

开启另一个终端,启动服务

这个终端也不要关闭。


---------------------------分割线------------------------------

上面是服务端的代码,下面来实现客户端的代码。

客户必须取得stub对象(我们的代理)以调用其中的方法。所以我们就需要RMI Registry的帮忙。客户从Registry中寻找(lookup)代理,就好像在电话簿里寻找一样,说:“我要找这个名字的stub”.

import java.rmi.*;

public class MyRemoteClient {
    public static void main (String[] args) {
        new MyRemoteClient().go(); 
    }

    public void go() {

        try{
            // 返回值是Object,所以要转换类型
            // 需要ip地址或主机名,以及服务器绑定/重绑定时用的名称
            MyRemote service = (MyRemote)Naming.lookup("rmi://127.0.0.1/RemoteHello"); 

            // 看起来和一般的方法调用没有区别!(除了必须注意RemoteException之外)
            String s = service.sayHello();

            System.out.println(s);

        } catch (Exception e) {
            e.printStackTrace(); 
        }
    }
}

编译,并且运行,发现输出“Hello world!”了!




OK !这就是RMI的基本过程了,当然实际应用中肯定还会有些变化的。



对于RMI, 程序员常犯的三个错误:

1. 忘了在启动远程服务之前先启动rmiregistry(要用Naming.rebind()注册服务, rmiregistry必须是运行的)

2. 忘了让变量和返回值的类型成为可序列化的类型(这种错误无法在编译期发现, 只会在运行时发现)

3. 忘了给客户提供stub类.




在敲上面的例子时, 我用IDE(Eclipse)来写过,但是步骤3编译时,遇到的问题:

java.rmi.ConnectException: Connection refused to host: 127.0.0.1

我试了其它电脑,还换了系统实现上述代码, 编译时都遇到了这个问题。

有没有人知道告诉我一下?




定义代理模式

代理模式为另一个对象提供一个替身或占位符以控制这个对象的访问







  • Subject, 为RealSubject和Proxy提供了接口, 通过实现同一个接口, Proxy在RealSubject出现的地方取代它
  • RealSubject是真正做事的对象,它是被proxy代理和控制访问的对象.
  • Proxy持有RealSubject的引用.在某些例子中, Proxy还会负责RealSubject对象的创建与销毁.客户和RealSubject的交互都必须通过Proxy.因为Proxy和RealSbuject实现相同的接口(Subject),所以任何用到RealSubject的地方,都可以用Proxy取代.Proxy也控制了对RealSubject的访问,在某些情况下,我们可能需要这样的控制.这些情况包括RealSubject是远程的对象, RealSubject创建开销大, 或RealSubject需要被保护.




代理模式的其他玩法

远程代理是一般代理模式的一种实现, 但是代理了模式的变体相当多

比如: 虚拟代理, 缓存代理,同步代理, 防火墙代理和写入时复制代理.

限于篇幅, 下次再继续学习



分享到:
评论

相关推荐

    设计模式学习笔记总结

    这里我们聚焦于C#语言中的设计模式学习笔记,涵盖了多种经典的设计模式,如合成模式、桥梁模式、装饰模式、享元模式、门面模式、命令模式、工厂方法、策略模式、代理模式以及状态模式。下面将对这些模式逐一进行详细...

    java 设计模式之代理模式(Proxy Pattern)实现代码及设计详解:动态代理模式、静态代理模式

    在这些模式中,代理模式(Proxy Pattern)是一种常用的结构型设计模式,它允许我们为一个对象创建一个代理,该代理对象在客户端和目标对象之间起到中介的作用,可以增加额外的功能或控制访问。 代理模式分为两种...

    设计模式C++学习之代理模式(Proxy)

    代理模式是一种设计模式,它是结构型模式之一,主要用于在客户端和目标对象之间建立一个代理对象,以便控制对目标对象的访问。在C++中,代理模式可以用来为其他对象提供一种代理以控制对这个对象的访问,或者增加...

    GOF之23种设计模式的C#实现:DesignPattern.zip

    - 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。 - 外观模式(Facade):为子系统提供一个统一的接口,使子系统更加易用。 - 适配器模式(Adapter):使两个不兼容的接口能够协同工作。 -...

    设计模式之代理模式proxy

    **设计模式之代理模式(Proxy Pattern)** 设计模式是软件工程中的一种最佳实践,它是在特定情境下解决常见问题的模板。代理模式是其中一种行为设计模式,它的核心思想是为一个对象提供一个替身或者代理,以控制对...

    设计模式 之 “代理模式[Proxy Pattern]”

    **代理模式(Proxy Pattern)**是软件设计模式中的结构型模式之一,它在对象访问控制、增加额外功能或在客户端与目标对象之间提供一个中介等方面有广泛的应用。在代理模式中,代理类作为真实对象的代表,它持有真实...

    Android设计模式之代理模式(Proxy Pattern)

    代理模式是设计模式的一种,它的主要目的是在不改变原有对象的基础上,为一个对象提供额外的功能或者控制对这个对象的访问。在Android开发中,代理模式的应用尤为常见,尤其在处理复杂的业务逻辑、网络请求、界面...

    300Java设计模式部分学习笔记

    2. 代理模式(Proxy Pattern):为其他对象提供一种代理以控制对这个对象的访问。 3. 桥接模式(Bridge Pattern):将抽象部分与实现部分分离,使它们都可以独立地变化。 4. 组合模式(Composite Pattern):将对象...

    代理模式 Proxy Pattern

    ### 代理模式 Proxy Pattern #### 概念定义 代理模式是一种结构型设计模式,它允许程序员为某对象创建一个代理对象来控制对该对象的访问。简单来说,就是在不修改原始类的基础上,通过引入代理对象来扩展类的行为...

    C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) (Level 300)

    本文将深入探讨C#中的一个关键设计模式——代理模式,它属于结构型模式的一种,适用于管理和控制对象的访问。我们将从概念、分类、实现方式以及实际应用等方面进行详细的讲解。 1. **代理模式概念**: 代理模式是一...

    设计模式学习笔记及其模式特点总结

    代理模式分为静态代理和动态代理,其中动态代理在Java中可以通过InvocationHandler接口和Proxy类实现。 2. **单例模式**: 单例模式确保一个类只有一个实例,并提供全局访问点。这种模式常用于控制资源的共享,如...

    设计模式学习笔记

    7. 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。 行为型模式涉及对象之间的责任分配,包括: 1. 责任链模式(Chain of Responsibility):将请求沿着处理者链传递,直到有对象处理为止。 2....

    设计模式整理代码-pattern.zip

    - 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。 - 外观模式(Facade):为子系统提供一个统一的接口,使得子系统的复杂性对客户透明。 - 适配器模式(Adapter):使两个不兼容的接口能够...

    C#设计模式学习笔记

    C#设计模式学习笔记是一份详尽的资源,适合任何希望深入了解如何在C#编程中应用设计模式的开发者。这份笔记涵盖了多种设计模式,旨在提升代码的可读性、可维护性和可扩展性,这些都是软件开发中至关重要的要素。 ...

    c++-设计模式之代理模式(Proxy)

    代理模式(Proxy Pattern)是一种结构型设计模式,用于为其他对象提供一种代理以控制对这个对象的访问。代理模式通常用于保护、延迟加载、记录请求等场景,可以在不改变原有对象的情况下为其增加新的功能。 代理...

    C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式)

    ### C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) #### 重要概念:代理模式 代理模式是一种常用的结构型设计模式,它通过为另一个对象提供一个代理,来控制对该对象的访问。这种模式在软件工程中...

    GoF 23种设计模式学习笔记

    "GoF 23种设计模式学习笔记" 是一个深入探讨这23个经典设计模式的资源,这些模式最初由Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides四位作者在1994年的著作《设计模式:可复用面向对象软件的基础》中...

    Proxy Pattern 代理模式

    Proxy Pattern 代理模式 采用JAVA实现,可以下载看看。

    设计模式之代理模式proxy.zip

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要的角色。代理模式允许我们为一个对象创建一个代理,这个代理对象在客户端和目标对象之间起到中介的作用,可以增强或控制对目标对象的访问。代理模式的主要...

    设计模式代理模式PPT学习教案.pptx

    代理模式(Proxy Pattern)是一种结构型设计模式,它提供了一个代理对象以控制对另外一个对象的访问。代理对象充当着中间人的角色,帮助客户端访问目标对象,并可以在访问过程中添加一些额外的操作。 知识点2:代理...

Global site tag (gtag.js) - Google Analytics