• 《设计模式之禅》学习笔记(十二)


    第12章 代理模式

    代理模式(Proxy Pattern)的定义如下:

    Provide a surrogate or placeholder for another object to control access to it.(为其他对象提供一种代理以控制对这个对象的访问。)

           

    代理模式也叫做委托模式,它是一种基本设计技巧。

           

    该模式下三种角色的定义:

    • Subject抽象主题角色

      抽象类或接口,是一个最普遍的业务类型定义

    • RealSubject具体主题角色

      被委托角色,是业务逻辑的具体执行者

    • Proxy代理主题角色

      委托类,负责对真实角色的应用,并负责预处理和善后工作。

           

    通用源代码:

    抽象主题类

    public interface Subject {

    // 定义一个方法

    public void request();

    }

    真实主题类

    public class RealSubject implements Subject {

    // 实现方法

    public void request() {

    // 业务逻辑处理

    }

    }

    代理类

    public class Proxy implements Subject {

    // 要代理哪个实现类

    private Subject subject = null;

    // 默认被代理者

    public Proxy() {

    this.subject = new RealSubject();

    }

    // 通过构造函数传递代理者

    public Proxy(Subject subject) {

    this.subject = subject;

    }

    // 实现接口中定义的方法

    public void request() {

    this.before();

    this.subject.request();

    this.after();

    }

    // 预处理

    private void before() {

    // do something

    }

    // 善后处理

    private void after() {

    // do something

    }

    }

         

    代理模式的优点:

    • 职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的食物,通过后期的代理完成一件事物,附带的结果就是编程简洁清晰。
    • 高扩展性。代理类可以在不做任何修改的情况下适应具体主题角色的变化。
    • 智能化。动态代理可以实现智能化。

         

    代理模式的扩展:

    普通代理

    在网络上代理服务器设置分为透明代理和普通代理,是什么意思呢?透明代理就是用户不用设置代理服务器地址,就可以直接访问,也就是说代理服务器对用户来说是透明的,不用知道它的存在;普通代理则是需要用户自己设置代理服务器的IP地址,用户必须知道代理的存在。设计模式中的普通代理就是我们要知道代理的存在,然后才能访问;强制代理则是调用者直接调用真实角色,而不用关心代理是否存在,其代理的产生是由真实角色决定的。

    普通代理的要求就是客户端只能访问代理角色,而不能访问真实角色。在该模式下,调用者只知道代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响。该模式非常适合对扩展性要求较高的场合。

    public class Client {

    public static void main(String[] args) {

    // 定义一个带练者

    IGamePlayer proxy = new GamePlayerProxy("张三");

    System.out.println("开始时间是:" + new Date());

    proxy.login("zhangsan", "password");

    proxy.killBoss();

    proxy.upgrade();

    System.out.println("结束时间是:" + new Date());

    }

    }

    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 + "在打怪");

    }

    @Override

    public void upgrade() {

    System.out.println(this.name + "又升了一级");

    }

    }

    public class GamePlayerProxy implements IGamePlayer {

    private IGamePlayer gamePlayer = null;

    public GamePlayerProxy(String name) {

    try {

    this.gamePlayer = new GamePlayer(this, name);

    } catch (Exception ex) {

         

    }

    }

    @Override

    public void login(String user, String password) {

    this.gamePlayer.login(user, password);

    }

    @Override

    public void killBoss() {

    this.gamePlayer.killBoss();

    }

    @Override

    public void upgrade() {

    this.gamePlayer.upgrade();

    }

    }

         

         

    强制代理

    一般的思维都是通过代理找到真实的角色,但是强制代理却是要"强制",你必须通过真实角色查找到代理角色,否则不能访问。

    public class Client {

    public static void main(String[] args) {

    IGamePlayer player = new GamePlayer("张三");

    IGamePlayer proxy = player.getProxy();

    System.out.println("开始时间是:" + new Date());

    proxy.login("zhangSan", "password");

    proxy.killBoss();

    proxy.upgrade();

    System.out.println("结束时间是:" + new Date());

    }

    }

    public 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 GamePlayerProxy(this);

    return this.proxy;

    }

    @Override

    public void killBoss() {

    if (this.isProxy()) {

    System.out.println(this.name + "在打怪!");

    } else {

    System.out.println("请使用指定的代理访问");

    }

    }

    @Override

    public void login(String user, String password) {

    if (this.isProxy()) {

    System.out.println("登录名为" + user + "的用户" + 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 (this.proxy == null) {

    return false;

    } else {

    return true;

    }

    }

    }

    public class GamePlayerProxy implements IGamePlayer, IProxy {

    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 void upgrade() {

    this.gamePlayer.upgrade();

    this.count();

    }

    @Override

    public IGamePlayer getProxy() {

    return this;

    }

    @Override

    public void count() {

    System.out.println("升级总费用是:150");

    }

    }

         

         

    虚拟代理

    虚拟代理就是在需要的时候才初始化主题对象,可以避免被代理对象较多引起的初始化缓慢的问题。其缺点是需要在每个方法中判断主题对象是否被创建。这就是虚拟代理,非常简单。

    public class Proxy implements Subject {

    private Subject subject = null;

    @Override

    public void request() {

    if (subject == null) {

    subject = new RealSubject();

    }

    subject.request();

    }

    }

         

    动态代理

    动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。

    动态代理实现代理的职责,业务逻辑实现相关的逻辑功能,两者之间没有必然的相互耦合的关系。对于日志、事务、权限等都可以在系统设计阶段不用考虑,而在设计后通过动态代理的方式加过去。

    public class Client {

    public static void main(String[] args) {

    // 定义一个主题

    Subject subject = new RealSubject();

    // 定义一个Handler

    InvocationHandler handler = new MyInvocationHandler(subject);

    // 定义主题的代理

    Subject proxy = DynamicProxy.newProxyInstance(subject.getClass().getClassLoader(), subject.getClass().getInterfaces(), handler);

    // 定义的行为

    proxy.doSomething("Finish!");

    }

    }

    public class MyInvocationHandler implements InvocationHandler {

    // 被代理的对象

    private Object target = null;

    // 通过构造函数传递一个对象

    public MyInvocationHandler(Object obj) {

    this.target = obj;

    }

    // 代理方法

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    Object result = method.invoke(this.target, args);

    return result;

    }

    }

    public class DynamicProxy<T> {

    public static <T> T newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) {

    // 寻找JoinPoint连接点,AOP框架使用元数据定义

    if (true) {

    // 执行一个前置通知

    (new BeforeAdvice()).exec();

    }

    // 执行目标,并返回结果

    return (T) Proxy.newProxyInstance(loader, interfaces, h);

    }

    }

    // 抽象主题

    public interface Subject {

    // 业务操作

    public void doSomething(String str);

    }

    // 真实主题

    public class RealSubject implements Subject {

    @Override

    public void doSomething(String str) {

    System.out.println("do something!--->" + str);

    }

    }

    public interface IAdvice {

    // 通知只有一个方法,执行即可

    public void exec();

    }

    public class BeforeAdvice implements IAdvice {

    @Override

    public void exec() {

    System.out.println("我是前置通知,我被执行了!");

    }

    }

  • 相关阅读:
    每天一个linux命令(57):ss命令
    [原][osg][osgearth]我眼中的osgearth
    [osg]osgDB的加载机制,使用3DS插件做参考(转,整理现有osgDB资料)
    [原][osgearth]osgearthviewer读取earth文件,代码解析(earth文件读取的一帧)
    [原][译][osgearth]Model Source Drivers模型驱动源(OE官方文档翻译)
    [原][译][osgearth]样式表style中参数总结(OE官方文档翻译)
    [原][osgearth]API加载earth文件的解析
    [原][译][osgearth]API加载地球(OE官方文档翻译)
    [osgearth]Earth文件详解
    [osgearth]通过API创建一个earth模型
  • 原文地址:https://www.cnblogs.com/qwertWZ/p/2835912.html
Copyright © 2020-2023  润新知