设计模式之代理模式

代理模式

概述

在日常生活中我们经常听到代理这个词语,它指的是代替别人进行工作。当有一些功能不需要“本人”亲自工作时,可以让代理人进行工作,但是有一些特殊的功能需要“本人”亲自工作时,那这些功能会交给“本人”实现。

示例程序

在示例程序中,我们模仿大老板签字,只有特定的文件需要大老板签字时,小老板才会将文件交给他,其余的文件小老板可以全权负责,可以理解为小老板是大老板的代理。

UML类图

名字说明
Boss大老板类
BossableBoss和BossProxy的实现接口
BossProxy小老板类

在这里插入图片描述

代码实现

Bossable

public interface Bossable {
    String getPrintName();//获取名称
    void setPrintName(String name);//设置名称
    void print(String str);//签名
}

Boss

public class Boss implements Bossable{
    private String name;

    public Boss() {
        heavyJob("正在生成Boss实例");
    }

    public Boss(String name) {
        this.name = name;
        heavyJob("正在生成Boss实例{" + name + "}");
    }

    @Override
    public String getPrintName() {
        return name;
    }

    @Override
    public void setPrintName(String name) {
        this.name = name;
    }

    @Override
    public void print(String str) {
        System.out.println("====" + name + "====");
        System.out.println(str);
    }

    private void heavyJob(String msg){
        System.out.println(msg);
        System.out.println("end");
    }
}

BossProxy

@NoArgsConstructor
public class BossProxy implements Bossable{
    private String name;
    private Boss boss;

    public BossProxy(String name) {
        this.name = name;
    }

    @Override
    public String getPrintName() {
        return name;
    }

    @Override
    public synchronized void setPrintName(String name) {
        if (boss != null){
            boss.setPrintName(name);
        }
        this.name = name;
    }

    @Override
    public void print(String str) {
        realize();
        boss.print(str);
    }

    private synchronized void realize(){
        if (boss == null){
            boss = new Boss(name);
        }
    }
}

test

@SpringBootTest
class Practice1500ApplicationTests {

    @Test
    void contextLoads() {
        Bossable proxy = new BossProxy("章副总");
        //还未生成boss实例
        System.out.println(proxy.getPrintName());
        proxy.setPrintName("张副总");
        System.out.println(proxy.getPrintName());
        //生成boss实例
        System.out.println("===============================");
        proxy.print("正版签名");
    }

}

//结果
章副总
张副总
===============================
正在生成Boss实例{张副总}
end
====张副总====
正版签名

参与角色

  • Subject(主体)

    Subject定义了使Boss和BossProxy角色之间具有一致性的接口,由于存在Subject角色,调用者不必在意他使用的时Boss还是BossProxy,在示例程序中由Bossable扮演该角色

  • Proxy(代理人)

    Proxy角色会尽量完成调用者交给他的任务,出现实在完成不了的任务才会交给本人去处理,在示例程序中由BossProxy扮演。

  • RealSubject(实际的主体)

    RealSubject角色会在Proxy角色处理不了任务的时候才会出现,在示例程序中由Boss扮演。

习题

习题一

在示例程序中,BossProxy类知道Boss类的存在,请修改BossProxy类,让其不必知道Boss

修改BossProxy

@NoArgsConstructor
public class BossProxy implements Bossable{
    private String name;
    private Bossable boss;
    private String className;

    public BossProxy(String name,String className) {
        this.name = name;
        this.className = className;
    }

    @Override
    public String getPrintName() {
        return name;
    }

    @Override
    public synchronized void setPrintName(String name) {
        if (boss != null){
            boss.setPrintName(name);
        }
        this.name = name;
    }

    @Override
    public void print(String str) {
        realize();
        boss.print(str);
    }

    private synchronized void realize(){
        if (boss == null){
            try {
                boss = (Bossable) Class.forName(className).newInstance();
                boss.setPrintName(name);
            } catch (Exception e) {
                System.out.println("找不到" + className + "类");
            }
        }
    }
}

习题二

在示例程序中,BossProxy类中setPrintName方法和realize方法都使用synchronized修饰,如果不适用synchronized会带来什么问题?

synchronized对这块方法加锁,如果在不加锁的情况下,多线程访问时很有可能出现BossProxy和Boss中的name属性不同

总结

其实小黄刚开始接触时,也觉得代理模式并没有什么必要,我们完全可以通过RealSubject角色来直接调用各种方法。

其实代理模式可以避免资源的浪费,假设我们创建Boss的过程非常的复杂,所有的复杂操作全部都在print方法中,这样在初始化的时候程序就会非常的慢。而Proxy角色成功将Boss的初始化方法推迟到了调用print方法时。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值