返回文章列表文章索引阅读全文
STARBLOG / 阅读手记
计科基础

设计模式之代理模式浅析

代理模式 在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行操作全部委派给代理对象, 隐藏实体的具体实现细节。 Proxy还可以与业务代码分离,部署到另外的服务器。业务代码中通过RPC来委派任务。 代理模式与父类和接口的异同 相同点:代理模式的作用和父类以及接口和组合的作用类似,都是为了聚合共用部分,减少公共部分的代码 不同点: 相比起父类,他们的语境不同,父类要表达的含义是 is

曦远 (DealiAxy)约 9 分钟
目录4 个章节

代理模式

  1. 在客户端与实体之间建立一个代理对象(proxy),客户端对实体进行操作全部委派给代理对象, 隐藏实体的具体实现细节。

  2. Proxy还可以与业务代码分离,部署到另外的服务器。业务代码中通过RPC来委派任务。

代理模式与父类和接口的异同

  • 相同点:代理模式的作用和父类以及接口和组合的作用类似,都是为了聚合共用部分,减少公共部分的代码
  • 不同点:
    • 相比起父类,他们的语境不同,父类要表达的含义是 is-a, 而代理要表达的含义更接近于接口, 是 has-a,而且使用代理的话应了一句话"少用继承,多用组合",要表达的意思其实也就是降低耦合度了
    • 相比起接口,他们实现的功能又不太一样,语境都是has-a,不过接口是has-a-function,而代理对象时是has-a-object,这个object是has-a-function的object,此外,接口是为了说明这个类拥有什么功能,却没有具体实现,实现了多态,而代理对象不但拥有这个功能,还拥有这个功能的具体实现
    • 对于组合来说,他比组合更具灵活性,比如我们将代理对象设为private,那么我可以选择只提供一部分的代理功能,例如Printer的某一个或两个方法,又或者在提供Printer的功能的时候加入一些其他的操作,这些都是可以的

实现代码

class Printer {    //代理对象,一台打印机
	public function printSth() {
		echo 'I can print <br>';
	}
	
	// some more function below
	// ...
}
 
class TextShop {    //这是一个文印处理店,只文印,卖纸,不照相
	private $printer;
	
	public function __construct(Printer $printer) {
		$this->printer = $printer;
	}
	
	public function sellPaper() {    //卖纸
		echo 'give you some paper <br>';
	}
	
	public function __call($method, $args) {    //将代理对象有的功能交给代理对象处理
		if(method_exists($this->printer, $method)) {
			$this->printer->$method($args);
		}
	}
}
 
class PhotoShop {    //这是一个照相店,只文印,拍照,不卖纸
	private $printer;
	
	public function __construct(Printer $printer) {
		$this->printer = $printer;
	}
	
	public function takePhotos() {    //照相
		echo 'take photos for you <br>';
	}
	
	public function __call($method, $args) {    //将代理对象有的功能交给代理对象处理
		if(method_exists($this->printer, $method)) {
			$this->printer->$method($args);
		}
	}
}

$printer = new Printer();
$textShop = new TextShop($printer);
$photoShop = new PhotoShop($printer);

$textShop->printSth();
$photoShop->printSth();

文印处理店和照相店都具有文印的功能,所以我们可以将文印的功能代理给一台打印机,这里打印机只有一个功能,假如打印机还有n个功能,我们使用__call()方法就能够省去很多重复的代码了

假如是使用继承,这样语境上就不合理,一个店显然不应该继承一台打印机

而使用接口,因为我们的功能实现都是一样,也没有必要去重新实现接口的功能

所以此处使用代理是最佳选择

Java的代理模式

Java中的代理模式实现其实类似,只不过Java没有__call()方法,需要手动声明printSth()方法,然后在方法体里去调用$printer的printSth()方法 或者可以用InvocationHandler代理接口来实现代理,

public interface InvocationHandler { 
   public Object invoke(Object proxy, Method method, Object[] args) throw Throwable; 
}

//日志代理实现   
public class LogHandler implement InvocationHandler{ 

   private Object target; 

   public LogHandler(Object target){ 
       this.target = target; 
   } 
   public Object invoke(Object proxy, Method method, Object[] args ) throw Throwable{ 

       //记录函数的初始状况参数等信息 
       log4j.info(“开始:方法”+ method.getName() + “参数”+Arrays.toString(args) );

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

       //记录函数的执行状况与返回值 
       log4j.info(“结束:方法”+ method.getName() + “返回值”+ result ); 

   }
}

//主函数   
public class Main{ 
   public static void main(String[ ] args){ 
	   //例子中生成报告的功能,生成报告需要记录日志。
       ReportGenerator reportGeneratorImpl  = new SMSReportGenerator (); 

       //通过系统提供的Proxy.newProxyInstance创建动态代理实例 
       ReportGenerator reportGenerator = (ReportGenerator ) Proxy.newProxyInstance(  
           reportGeneratorImpl.getClass().getClassLoader(), 
           reportGeneratorImpl.getClass().getInterfaces(), 
           new LogHandler(reportGeneratorImpl)
       ) ; 
       ...
   }
}

但是 Java Reflection API 实现的动态代理结构十分复杂,不易理解。 有接触过Spring框架的朋友应该对Spring的AOP(面向切片编程)有所了解,Spring使用注解的方式来实现代理模式比Java Reflection API方式直观得多了。本文就不再赘述了。

_EOF_

设计模式之代理模式浅析

本文作者:
程序设计实验室
版权声明:
本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

相关文章

操作系统学习二:进程同步与互斥之生产者-消费者问题--NetCore实现

目的 1. 掌握进程(线程)的同步与互斥。 2. 掌握生产者消费者问题的实现方法。 3. 掌握VC的多线程编程方法。 内容 本实验要求设计并实现一个进程,该进程拥有3个生产者线程和1个消费者线程,它们使用10个不同的缓冲区。需要使用如下信号量: 一个mutex信号量,用以阻止生产者线程和消费者线程同时操作缓冲区队列; 一个full信号量,当生产者线程生产出一个物品时可以用它向消费者线程发出信号;

2022-06-17 · 计科基础 · 约 1 分钟

编译原理学习一,去除代码中的注释

前言 开始学习编译原理了耶~ 关于编译原理的所有练习,按照老规矩,还是用我最喜欢的C#语言来实现,运行在.NetCore平台上~ 关于这个系列的所有代码已经上传到github了,项目主页: https://github.com/Deali-Axy/CompilerConstructionLearning 本次题目 对C或C++等高级程序设计语言编写的源程序中的//注释和/…/注释进行删除,保留删除

2022-06-17 · 计科基础 · 约 1 分钟

软件工程课程思维导图

结构如下 软件工程 什么是软件工程 方法 系统的 规范的 可量化的 过程 软件开发 运行 维护 构成的主要要素 人 项目 过程 方法 工具 软件制品 影响软件工程进步的动力 硬件能力 软件技术 社会需求 科学技术水平 软件的8个质量要素 正确性 软件满足需求规约的程度 完成用户目标的程度 可用性 学习、使用成本 操作软件 输入数据 解释软件输出结果 可靠性 完成预期功能概率 成功运行概率 有效性

2022-06-17 · 计科基础 · 约 1 分钟

操作系统学习一:NetCore-实现模拟多道程序设计的简单处理机调用

前言 道程序设计中,经常是若干个进程同时处于就绪状态,为了使系统中的各进程有条不紊地运行,必须选择某种调度策略,以选择一个进程占用处理机。本次实验设计一个模拟单处理机调度的算法,以加深对处理机调度算法的理解。 要求 按照时间片轮转算法设计模拟调度程序。 输出进程的调度过程。 思路分析 由于本实验是按照处理机调度算法模拟实现处理机的调度,与真正的处理机调度过程并不完全相同,比如没有实现中断(时间片设

2022-06-17 · 计科基础 · 约 1 分钟

讨论

共 0 条

良言一句三冬暖,恶语伤人六月寒。

加载评论中…