码迷,mamicode.com
首页 > 其他好文 > 详细

代理模式

时间:2015-05-18 22:29:56      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:

  GOF:为其他对象提供一种代理以控制对这个对象的访问。

  类图:

技术分享

  适用性: 

  • 远程代理 :也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
  • 虚拟代理:根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。
  • 安全代理:控制真实对象访问时的权限。
  • 智能指引:当调用真实的对象时,代理处理另外一些事。

  代理模式还有一种称为copy-on-write的优化方式,如果copy一个对象开销很大,那么只有在改变对象时才copy,如果没有改变对象则用代理来调用原来的对象。


 

  (1)一个简单的代理模式例子:小明春节想要买火车票回家,但是他工作很忙,因此他找了他的朋友小鹏帮他买票。

  分析:这里小鹏就是一个代理。

public class 代理模式 {
    public static void main(String[] args) {
        Person xiaoMing = new Person();
        proxy p = new proxy(xiaoMing);
        p.goToTrainStation();
        p.buyTicket();
    }
    
}
interface goBuyTicket {
    void goToTrainStation();
    void buyTicket();
}

class Person implements goBuyTicket {

    @Override
    public void goToTrainStation() {
        System.out.println("Go to the trainStation");
    }

    @Override
    public void buyTicket() {
        System.out.println("Buy ticket");
    }
}

class proxy implements goBuyTicket {
    private Person xiaoMing;
    public proxy(Person xiaoMing) {
        this.xiaoMing = xiaoMing;
    }
    @Override
    public void goToTrainStation() {
        xiaoMing.goToTrainStation();
    }

    @Override
    public void buyTicket() {
        xiaoMing.buyTicket();
    } 
}

  不管是小明还是代理,他们都有能力去火车站买票,因此实现同一个买票接口。在代理中,放置被代理的对象。

  (2)智能指引

  例子:Smart Pointer,这在C++中十分常用,也十分powerful,特别是管理指针。

#include <iostream>
#include <memory>
using namespace std;

class coo {
public:
    void request() { cout << "coo request() " << endl; }
    ~coo() { cout << "coo destructor" << endl; }
};

int main() {
    shared_ptr<coo> sp(new coo());
    sp->request(); //可以像使用coo的指针一样
    return 0;
    //自动释放coo(利用了sp是临时对象,会调用自己的析构函数)
}

  (3)安全代理

  例子:系统管理员和普通用户的权限是不同的,比如修改root密码只有管理员能进行(管理员还能修改普通用户的密码),普通用户不能进行;而查看一些普通数据则全部用户都能进行。

#include <iostream>
#include <string>
using namespace std;

class User {
public:
    virtual string getName() { return "User"; }
};

class NormalClient : public User {
public:
    virtual string getName() { return "Normal client"; }
};

class Root : public User {
public:
    virtual string getName() { return "root"; }
};

class Subject {
public:
    virtual void changeRootPassword() = 0;
    virtual void viewNormalData() = 0;
};

class OS : public Subject {
public:
    //只有root能执行
    void changeRootPassword() { cout << "修改管理员的密码" << endl; }
    //所有用户都能执行
    void viewNormalData() { cout << "查看普通的数据" << endl; }
};

class OSProxy : public Subject {
public:
    OSProxy(User *user) {
        m_os = new OS();
        m_user = user;
    }
    void setUser(User *user) {
        m_user = user;
    }
    void changeRootPassword() {
        if(m_user->getName() == "root")
            m_os->changeRootPassword();
        else
            cout << "权限不够" << endl;
    }

    void viewNormalData() { m_os->viewNormalData(); }

private:
    OS *m_os;
    User *m_user;
};

int main() {
    cout << "以管理员身份操作" << endl;
    OSProxy *proxy = new OSProxy(new Root());
    proxy->changeRootPassword();
    proxy->viewNormalData();

    cout << endl << "以普通用户身份操作" << endl;
    NormalClient *client = new NormalClient();
    proxy->setUser(client);
    proxy->changeRootPassword();
    proxy->viewNormalData();
}

  (4)虚拟代理

  例子:如果是获取类的名字,那么代理直接返回被代理者的名字,不需要马上实例化,如果是调用operation()方法才实例化被代理者。

#include <iostream>
using namespace std;

class Subject {
public:
    virtual void getName() = 0;
    virtual void operation() = 0;
};

class BigClass : public Subject {
public:
    BigClass() { cout << "实例化已花费半小时" << endl; }
    virtual void getName() {
        cout << "BigClass" << endl;
    }
    virtual void operation() {
        cout << "利用实例来进行操作" << endl;
    }
};

class Proxy : public Subject {
public:
    //我们预先已知道getName的结果,不需要使用BigClass的实例
    virtual void getName() {
        cout << "BigClass" << endl;
    }
    //直到调用operation()时才实例化BigClass
    virtual void operation() {
        if(m_bigClass == nullptr)
            m_bigClass = new BigClass();
        m_bigClass->operation();
    }
private:
    BigClass *m_bigClass;
};

int main() {
    Proxy *p = new Proxy();
    p->getName();
    p->operation();
    delete p;
}

 

  小结:代理模式让我们编写类时只关注功能的实现,而其他一些细节,比如内存管理,访问控制等交给代理来做。

代理模式

标签:

原文地址:http://www.cnblogs.com/programmer-kaima/p/4382892.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!