昭通市网站建设_网站建设公司_Python_seo优化
2025/12/29 14:37:30 网站建设 项目流程

设计模式实践:代理模式实现婚介所的权限控制

在软件开发中,当需要为对象的访问添加额外控制(如权限验证、日志记录、缓存处理)时,直接修改对象本身会违反“单一职责原则”。代理模式通过引入“代理对象”,在不改变原始对象代码的前提下,为其提供间接访问并附加额外功能。本文以“婚介所权限控制”为例,分享代理模式的设计思想与实践应用。

一、代理模式核心思想

代理模式是一种结构型设计模式,核心目标是控制对象的访问,其关键结构包括:

  1. 抽象主题(Subject):定义真实主题和代理的共同接口,确保代理可替代真实主题;

  2. 真实主题(Real Subject):实现核心业务逻辑,是代理的目标对象;

  3. 代理(Proxy):持有真实主题的引用,实现抽象主题接口,在调用真实主题前后添加额外逻辑;

  4. 客户端(Client):通过代理访问真实主题,无需直接与真实主题交互。
    本次实践中,婚介所作为“代理”,在提供“找对象”核心服务(真实主题)前,需先验证用户年龄(额外控制):未满18岁禁止服务,年龄过大也拒绝服务,只有符合年龄条件的用户才能享受真实服务。

二、类图设计

| Center | // 抽象主题:婚介中心
+-------------------+- name: String // 婚介所名称
+-------------------+- Center(name: String) // 构造方法- findLove(person: Person): void // 核心接口:找对象
+-------------------+
^
|
+-------+-------+ +-------+-------+
| | | |
| Marry | | MarryProxy | // 代理类:婚介所代理
+---------------+ +---------------+
| + Marry(name: String) | - marry: Marry // 持有真实主题引用
| + findLove(person: Person): void // 实现核心服务
+---------------+ | + MarryProxy(name: String)
| + findLove(person: Person): void // 代理逻辑(年龄验证+调用真实服务)
+---------------+
+-------------------+
| Person | // 实体类:用户信息
+-------------------+- name: String // 姓名- age: int // 年龄
+-------------------+- Person(name: String, age: int)- getName(): String- getAge(): int- setName(name: String): void- setAge(age: int): void
+-------------------+

三、完整代码实现

1. 实体类:Person(用户信息)

封装用户的姓名和年龄,提供 getter/setter 方法供外部访问。

/**
* 实体类:表示需要婚介服务的用户
*/
public class Person {
private String name;
private int age;
// 构造方法:初始化姓名和年龄
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Getter和Setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

2. 抽象主题:Center(婚介中心接口)

定义婚介服务的核心接口,统一真实主题和代理的行为规范。

/**
* 抽象主题类:婚介中心
* 定义找对象的核心业务接口,供真实主题和代理实现
*/
public abstract class Center {
protected String name; // 婚介所名称
// 构造方法:初始化婚介所名称
public Center(String name) {
this.name = name;
}
/**
* 抽象方法:找对象服务
* @param person 需要找对象的用户
*/
public abstract void findLove(Person person);
}

3. 真实主题:Marry(实际婚介服务)

实现抽象主题的核心接口,提供真实的“找对象”服务,不关心额外控制逻辑。

/**
* 真实主题类:实际的婚介服务
* 专注于核心业务逻辑,不处理权限验证等额外功能
*/
public class Marry extends Center {
// 构造方法:初始化婚介所名称
public Marry(String name) {
super(name);
}
@Override
public void findLove(Person person) {
// 核心服务逻辑:为符合条件的用户提供找对象服务
System.out.printf("%s:%s,我们会为您找到合适的伴侣!%n", 
name, person.getName());
}
}

4. 代理类:MarryProxy(婚介所代理)

持有真实主题的引用,实现抽象接口,在调用真实服务前添加年龄验证逻辑,调用后可扩展后置处理。

/**
* 代理类:婚介所代理
* 控制对真实婚介服务的访问,添加年龄验证等额外逻辑
*/
public class MarryProxy extends Center {
// 持有真实主题的引用:通过代理访问真实服务
private Marry marry;
// 构造方法:初始化婚介所名称,并创建真实主题实例
public MarryProxy(String name) {
super(name);
this.marry = new Marry(name);
}
@Override
public void findLove(Person person) {
// 前置处理:年龄权限验证(代理模式的核心额外功能)
if (person.getAge() < 18) {
System.out.printf("%s:%s,对不起!不能早恋!%n", 
name, person.getName());
return; // 终止服务,不调用真实主题
} else if (person.getAge() >= 100) {
System.out.printf("%s:%s,对不起!您年龄太大了!%n", 
name, person.getName());
return; // 终止服务,不调用真实主题
}
// 核心逻辑:调用真实主题的服务
marry.findLove(person);
// 后置处理:可扩展额外功能(如服务反馈、后续跟进提示)
System.out.printf("服务已完成,感谢使用%s!%n", name);
}
}

5. 客户端测试:Client

通过代理类访问婚介服务,测试不同年龄用户的服务效果,验证代理的权限控制逻辑。

/**
* 客户端测试类:演示代理模式的使用
*/
public class Client {
public static void main(String[] args) {
// 创建代理对象(客户端只与代理交互,不直接访问真实主题)
Center marriageAgency = new MarryProxy("幸福婚介所");
// 测试不同年龄的用户
Person youngPerson = new Person("美羊羊", 16); // 年龄过小(16岁)
Person adultPerson = new Person("喜羊羊", 29); // 年龄正常(29岁)
Person oldPerson = new Person("慢羊羊", 105); // 年龄过大(105岁)
System.out.println("=== 幸福婚介所服务测试 ===");
// 测试1:年龄正常的用户
System.out.println("\n【测试1】年龄正常用户");
marriageAgency.findLove(adultPerson);
// 测试2:年龄过小的用户
System.out.println("\n【测试2】年龄过小用户");
marriageAgency.findLove(youngPerson);
// 测试3:年龄过大的用户
System.out.println("\n【测试3】年龄过大用户");
marriageAgency.findLove(oldPerson);
}
}

四、运行结果与验证

=== 幸福婚介所服务测试 ===
【测试1】年龄正常用户
幸福婚介所:喜羊羊,我们会为您找到合适的伴侣!
服务已完成,感谢使用幸福婚介所!
【测试2】年龄过小用户
幸福婚介所:美羊羊,对不起!不能早恋!
【测试3】年龄过大用户
幸福婚介所:慢羊羊,对不起!您年龄太大了!

结果分析:

  1. 权限控制生效:年龄小于18岁或大于等于100岁的用户被拒绝服务,未调用真实主题的核心逻辑;

  2. 正常服务流程:符合年龄条件的用户,代理先验证权限,再调用真实服务,最后执行后置处理;

  3. 客户端无感知:客户端只需调用代理的findLove()方法,无需关心权限验证细节,实现了解耦。

五、代理模式的核心优势与适用场景

核心优势

  1. 单一职责原则:真实主题专注于核心业务,代理负责额外控制(如权限、日志),职责分离;

  2. 扩展性强:新增额外功能(如日志记录、缓存、事务管理)时,无需修改真实主题和客户端代码;

  3. 保护真实主题:通过代理屏蔽外部直接访问,可控制访问频率、权限等,保护核心服务;

  4. 灵活性高:客户端通过代理访问服务,可动态切换真实主题或调整代理逻辑,无需改动客户端。

适用场景

  1. 权限控制:如登录验证、年龄限制、角色权限等(如本次婚介所年龄验证);

  2. 日志记录:记录接口调用时间、参数、结果,便于调试和监控;

  3. 缓存处理:缓存频繁访问的结果,减少真实服务的调用次数(如数据库查询缓存);

  4. 远程代理:为远程对象提供本地代理(如RPC框架中的代理);

  5. 延迟加载:延迟初始化真实主题,节省系统资源(如大型对象的懒加载)。

六、代理模式的常见类型

代理类型 核心特点 适用场景
静态代理 代理类编译时已确定,与真实主题实现同一接口 简单场景,额外逻辑固定(如本次实践)
动态代理 代理类运行时动态生成,无需手动编写代理代码 复杂场景,需灵活扩展代理逻辑(如Spring AOP)
远程代理 代理本地对象,访问远程服务器上的真实主题 分布式系统,远程服务调用(如RPC)
虚拟代理 延迟初始化真实主题,仅在需要时创建 大型对象、资源密集型对象的加载
保护代理 控制真实主题的访问权限,验证用户合法性 权限管理、访问控制(如本次实践)

七、实践总结

  1. 代理模式的核心是“代理对象转发请求+附加额外逻辑”,不改变真实主题的核心功能;

  2. 本次实践中,MarryProxy作为代理类,通过前置年龄验证控制服务访问,既保护了真实主题,又简化了客户端操作;

  3. 静态代理实现简单,适合额外逻辑固定的场景;若需灵活扩展(如新增多种验证规则),可使用动态代理(如Java的Proxy类、CGLIB);

  4. 实际开发中,代理模式的典型应用包括:Spring AOP的切面编程、MyBatis的Mapper代理、权限框架的访问控制等。
    通过本次婚介所权限控制的实践,我深刻理解了代理模式如何在不侵入核心代码的前提下,为对象访问添加额外功能。合理运用代理模式,能让系统架构更清晰、扩展性更强,同时符合设计模式的“开闭原则”。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询