大家好,我是一位在java学习圈中不愿意透露姓名并苟且偷生的小学员,如果文章有错误之处,还望海涵,欢迎多多指正
如果你从本文 get 到有用的干货知识,请帮忙点个赞呗,据说点赞的都拿到了offer
简单的认识代理模式:
代理模式(Proxy Pattern),又叫委托模式,是指为其他对象提供一种代理,以控制对这个对象的访问,属于结构型设计模式
目的是为了保护目标对象或增强目标对象
代理模式的两种实现方式:静态代理和动态代理
接下来我们先实现静态代理:
问题引申:
1,静态代理:
在思考什么是静态代理前我们先思考一个生活中的现象…
茶叶 和 茶农(生产商)是什么关系?
很明显 茶叶 是 茶农 种植生产的,那么种植生产的结尾肯定会产生( 可以认为使用到了 )茶叶,故二者的关系是use a(这里如果觉得不好理解可以看之后的代码及注释)
那么给茶农设计两个方法-
- 生产茶
- 卖茶
案例代码
package proxy;
/**
* 这是一个龙井茶类
*/
public class DragonWellTea {
//随便设计几个方法
public void teaSmell(){
System.out.println("这个茶是茶农纯天然种植的,味道真香(醇香)");
}
public void drinkTeaMethod(){
System.out.println("这个茶是茶农纯天然种植的,只需要开水泡上3分钟即可");
}
}
//================================================================================
package proxy;
/**
* 这是一个龙井茶农直销的商店类
*/
public class DragonWellTeaStore {
//给茶农的店设计两个方法 生产茶 卖茶
public DragonWellTea productDragonWellTea(){
//茶农种植生产茶的过程(方法中用到了另一个类的对象,故 茶农 和 茶 的关系是use a)
DragonWellTea dragonWellTea = new DragonWellTea();
//将生产得到的茶返回出去
return dragonWellTea;
}
public DragonWellTea sellDragonWellTea(){
//卖茶首先要生产茶
DragonWellTea dragonWellTea = this.productDragonWellTea();
//将生产得到的茶卖出去(即返回给买茶的人)
return dragonWellTea;
}
}
//==================================================================================
package proxy;
/**
* 这是一个测试类
*/
public class TestProxy {
public static void main(String[] args){
//先有茶农才能卖茶
DragonWellTeaStore store = new DragonWellTeaStore();
//卖茶给买茶的人
DragonWellTea dragonWellTea = store.sellDragonWellTea();
//买茶的人开始品茶(这里就不单独设计一个Person类了,因为我们的研究重点不在这)
dragonWellTea.drinkTeaMethod();
dragonWellTea.teaSmell();
}
}
茶确实是卖出去了,但是茶农终究卖不完(种植生产太多了),那么该怎么办呢?
所以茶农找到了代理商(代理商赚差价)
那么我们在原有代码的基础上接着设计吧,先是代理商店的黑心小作坊(一个方法)出现了,接着生茶出了假龙井,
但是仔细一想,顾客买了一次假龙井,而代理商跑路了,那么顾客就哑巴吃黄连有苦说不出了,只能告诉大家,那家店的龙井不要买
代理商灵机一动,这么卖下去,最后就卖不出去了,于是给自己的店和自己的假茶做了一个包装,外表包装成真的店的和真的茶
如何实现以假乱真呢?通过规则,多态的方式,茶有茶的规则,店有店的规则,至少用户(主方法)用的时候看起来是一样的
首先实现龙井茶类
package proxystatic;
/**
* 这是一个龙井茶类
*/
public class DragonWellTea implements Tea{
//随便设计几个方法
public void teaSmell(){
System.out.println("这个茶是茶农纯天然种植的,味道真香(醇香)");
}
public void drinkTeaMethod(){
System.out.println("这个茶是茶农纯天然种植的,只需要开水泡上3分钟即可");
}
}
接着是黑心茶类
package proxystatic;
/**
* 这是一个代理商生产的黑心茶
*/
public class AgentTea implements Tea{
@Override
public void teaSmell() {
System.out.println("这是代理商生产的假龙井,味道苦涩");
}
@Override
public void drinkTeaMethod() {
System.out.println("这是代理商生产的假龙井,需要开水泡10分钟才能饮用");
}
}
黑心茶和龙井茶都是茶,所以实现同一个茶接口
卖茶的时候代理商直接返回这个接口类型就好了
package proxystatic;
/**
* 定义接口的目的 为了统一规则
* 接口 只有抽象方法 不做具体实现 (1.8版本之后可以写具体方法)
*/
public interface Tea {
//茶的味道
void teaSmell();
//泡茶的方式
void drinkTeaMethod();
}
生产龙井茶的茶农商店类
package proxystatic;
/**
* 这是一个龙井茶农直销的商店类
*/
public class DragonWellTeaStore implements Store{
//给茶农的店设计两个方法 生产茶 卖茶
private Tea productDragonWellTea(){
//茶农种植生产茶的过程(方法中用到了另一个类的对象,故 茶农 和 茶 的关系是use a)
DragonWellTea dragonWellTea = new DragonWellTea();
//将生产得到的茶返回出去
return dragonWellTea;
}
public Tea sellDragonWellTea(){
//卖茶首先要生产茶
Tea dragonWellTea = this.productDragonWellTea();
//将生产得到的茶卖出去(即返回给卖茶的人)
return dragonWellTea;
}
}
生产黑心茶的商店类(这个类实际上就是代理生产龙井茶商店的代理类)
package proxystatic;
/**
* 这是一个静态代理类
* 目的是为了在顾客和商店中间添加一个层次
* 这个层次可以改变原有真实商店的执行 也可以沿用真实商店的执行
* 有了这层代理 设计就更灵活
*
* 可以理解这个静态代理类商店是茶农商店授权的 只能卖茶农规定的商品 即便是假货也得是假龙井
*
* 代理对象与目标对象的认知:
* 代理对象就是我们要代理目标对象 在目标对象原有功能的基础上添加一些独特的实现(做一些手脚)
* 注意原有功能的基础指的是目标对象的接口
*/
public class AgentTeaStore implements Store{
//设计一个属性==(茶农 只有茶农能生产龙井) 聚合 一个类的属性中存储另一个类的对象 has-a
//补充设计这个属性的目的,代理商卖的茶从哪里来?无非是茶农生产然后转卖给代理商的
//有人可能会说为啥不当参数传到方法里
private DragonWellTeaStore DragonWellTeaStore = new DragonWellTeaStore();
//自己的小作坊生产假茶
private AgentTea productAgentTea() {
AgentTea agentTea = new AgentTea();
return agentTea;
}
@Override
public Tea sellDragonWellTea() {
//茶农转卖给代理商去卖 一开始是真茶
// Tea dragonWellTea = DragonWellTeaStore.sellDragonWellTea();
// return dragonWellTea;
//现在卖自己生产的假茶
AgentTea agentTea = this.productAgentTea();
return agentTea;
}
}
黑店与龙井茶店都是店,故实现同一个接口来统一店的规则
主方法创建店的时候就用Store 来接收即可,这样代理商卖茶的方法名与真店卖茶的方法名就一致了,真店怎么卖,代理商就怎么卖,这样用户(主方法)用起来就感觉跟真的一样了
package proxystatic;
/**
* 这个接口的出现是为了统一所有商店规范
* 有了这个规范 以后的店面就一样了
*/
public interface Store {
//这个接口只规范卖茶的规则,至于下面的人的茶是怎么来的只有自己知道哈哈...
Tea sellDragonWellTea();
}
接下来看看测试类
package proxystatic;
/**
* 这是一个测试类
*/
public class TestStaticProxy {
public static void main(String[] args){
// //先有茶农才能卖茶
// DragonWellTeaStore store = new DragonWellTeaStore();
// //卖茶给卖茶的人
// DragonWellTea dragonWellTea = store.sellDragonWellTea();
//代理商卖茶
Store dragonWellTeaStore1 = new AgentTeaStore();
Tea dragonWellTea1 = dragonWellTeaStore1.sellDragonWellTea();
//买茶的人开始品茶(这里就不单独设计一个Person类了)
dragonWellTea1.drinkTeaMethod();
dragonWellTea1.teaSmell();
//多态(父类引用指向子类对象)让顾客傻傻分不清,从外表上看二者没有区别
//代理模式----静态代理(关注商店)
//茶农直销
Store dragonWellTeaStore2 = new DragonWellTeaStore();
Tea dragonWellTea2 = dragonWellTeaStore2.sellDragonWellTea();
//买茶的人开始品茶(这里就不单独设计一个Person类了)
dragonWellTea2.drinkTeaMethod();
dragonWellTea2.teaSmell();
}
}
总结:
先通过一张图来直观的感受静态代理
黑心店(代理商的店)和茶农的店实现同一个接口,目的就是为了让顾客分辨不出来,两个店类的方法名完全一致,顾客使用时也是一致看不出来有什么区别,使用者自认为用的类是自己知道的那个真实的类,实际上不仅类不一样我们在功能上也做了一点手脚,通过静态代理用户并不能识别,因为功能一致(可以理解为方法名相同)
静态代理应用场景:隐藏真实类的实现,在类的某个方法实现的前后做点手脚,增加功能
看完了小伙伴们是不是对静态代理有了更深刻的理解呢?希望这篇文章能帮到小伙伴们更好的理解静态代理模式
之后开始慢慢的更新每一种设计模式,通过生动形象的生活现象举例带你感受设计模式的世界,其实设计模式不难,只是当我们面对某个场景时想不到用哪个设计模式该不该用设计模式…
博客内容来自腾讯课堂渡一教育拓哥,以及自己的一些理解认识,同时看了其他大牛写的设计模式技术文章综合总结出来的