五、代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一个代理以控制对这个对象的访问。代理对象通常会对真实对象的请求进行一些处理(例如延迟初始化、访问控制、日志记录等),它能够在不改变目标对象的情况下,给目标对象添加额外的功能。

主要组成部分:

  1. 主题接口(Subject)

    • 定义了真实对象和代理对象的共同接口。客户端通过这个接口与真实对象交互。
  2. 真实主题(Real Subject)

    • 实现了主题接口,代表真实的对象,包含实际的业务逻辑。
  3. 代理(Proxy)

    • 也是实现主题接口的类,它持有一个真实主题的引用,并对真实主题的请求进行处理。

优点:

  1. 控制访问:可以在代理类中添加访问控制逻辑,从而增强安全性。

  2. 延迟加载:代理对象可以在实际需要时才创建真实对象,提高性能。

  3. 更好的管理:可以通过代理对请求进行日志记录、缓存等管理。

  4. 透明性:客户端与真实对象之间的交互是透明的,因为它们通过相同的接口来访问。

使用场景:

  • 当需要控制对某个对象的访问时(例如,权限控制)。
  • 当需要在访问对象时进行附加操作时(如延迟加载)。
  • 当需要对访问对象进行代理(如网络请求或缓存)。

静态代理

GO: 

golang 实现静态代理,有 Golang 和 java 的差异性,我们无法比较方便的利用反射实现动态代理,但是我们可以利用** go generate **实现类似的效果,并且这样实现有两个比较大的好处,一个是有静态代码检查,我们在编译期间就可以及早发现问题,第二个是性能会更好

package proxy

import (
	"fmt"
	"log"
	"time"
)

// IUser 接口
type IUser interface {
	// Login 登陆函数
	Login(username string, password string) error
}

// User 用户实现IUser接口
type User struct {
}

// Login 用户登录
func (u *User) Login(username string, password string) error {
	// 不实现细节
	fmt.Println("登陆成功......")
	return nil
}

// UserProxy 代理类 也实现 IUser 接口
type UserProxy struct {
	user *User
}

// NewUserProxy NewUserProxy
func NewUserProxy(user *User) *UserProxy {
	return &UserProxy{
		user: user,
	}
}

func (u *UserProxy) Login(username string, password string) error {
	// before 这里可能会有一些统计的逻辑
	start := time.Now()

	// 这里是原有的业务逻辑
	if err := u.user.Login(username, password); err != nil {
		return err
	}

	// after 这里可能也有一些监控统计的逻辑
	log.Printf("user login cost time: %s", time.Now().Sub(start))

	return nil
}
package proxy

import (
	"github.com/stretchr/testify/require"
	"testing"
)

func TestProxy(t *testing.T) {
	// 构建代理对象
	proxy := NewUserProxy(&User{})
	//调用登陆
	err := proxy.Login("test", "password")
	require.Nil(t, err)
}
JAVA:
public interface IUser {
    public void login(String username, String password);
}
public class User implements IUser{
    @Override
    public void login(String username, String password) {
        // 不做具体实现
        System.out.println("登陆成功");
    }
}
public class UserProxy implements IUser{
    private User user;

    @Override
    public void login(String username, String password) {
        // 可以在请求之前进行某些处理
        if (user == null) {
            user = new User();
        }
        System.out.println("Proxy: Pre-processing before request.");
        user.login(username, password); // 转发请求
        System.out.println("Proxy: Post-processing after request.");
    }
}

 

public class ProxyTest {

    @Test(description = "静态代理")
    public void proxyTest(){
        UserProxy userProxy = new UserProxy();
        userProxy.login("xxx", "yyy");
    }
}

动态代理 

GO:待补充。。。。
JAVA:
1. 基于 JDK 的动态代理

JDK 的动态代理通过 java.lang.reflect.Proxy 类和 InvocationHandler 接口来实现。它需要指定一个接口,然后通过代理对象来调用真实对象的方法。

使用步骤:
  1. 定义接口
  2. 创建真实主题类
  3. 实现 InvocationHandler 接口
  4. 创建代理对象
  5. 调用方法
//1.定义接口
public interface Subject {
    public void request();
}
//2.创建真实主题类
public class RealSubject implements Subject{

    @Override
    public void request() {
        System.out.println("RealSubject: Handling request.");
    }
}
//3.动态代理处理器 实现 InvocationHandler 接口
public class DynamicProxyHandler implements InvocationHandler {
    private Object target;

    public DynamicProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 在调用目标方法之前执行一些操作
        System.out.println("Proxy: Pre-processing before request.");
        Object result = method.invoke(target, args); // 调用真实方法
        // 在调用目标方法之后执行一些操作
        System.out.println("Proxy: Post-processing after request.");
        return result;
    }
}
@Test(description = "动态代理-JDK")
    public void dynamicJDKTest(){
        RealSubject realSubject = new RealSubject();
        Subject proxyInstance = (Subject) Proxy.newProxyInstance(
                realSubject.getClass().getClassLoader(),
                realSubject.getClass().getInterfaces(),
                new DynamicProxyHandler(realSubject)
        );
        proxyInstance.request();
    }
2. 基于 CGLIB 的动态代理

CGLIB(Code Generation Library)是一种用于在运行时生成类的库,它通过继承来创建代理对象。CGLIB 适用于代理类没有接口的情况。

使用步骤:
  1. 添加 CGLIB 依赖(如果是 Maven 项目,添加相关依赖)。
  2. 创建一个代理工厂
  3. 创建代理对象
  4. 调用方法

... 模版代码就不加了.网上都有。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值