如何让同一类的两个Java对象行为不同?单向访问客户队列实现
嘿,这个场景我之前做模拟系统时也碰到过,本质就是要让同一类的不同实例拥有差异化的权限逻辑,下面给你几个实用的实现思路:
针对你的需求——Service A可访问B的队列但B不能访问A的队列,这里有三种靠谱的实现方式,你可以根据场景复杂度选择:
1. 继承+多态:子类专属行为
最直观的方式是给Service创建两个子类,把访问控制的差异逻辑放到子类里实现,利用多态特性让不同实例表现不同行为。
先定义父类Service,包含通用属性和方法:
import java.util.ArrayList; public abstract class Service { protected ArrayList<Customer> waitingQueue; public Service() { this.waitingQueue = new ArrayList<>(); } // 抽象方法:让子类实现自己的访问权限判断 public abstract boolean canAccessTargetQueue(Service target); // 统一的队列处理入口,先判断权限再执行 public void processTargetQueue(Service target) { if (canAccessTargetQueue(target)) { // 这里写具体的队列处理逻辑,比如转移客户、执行服务等 System.out.println("开始处理目标队列..."); target.waitingQueue.forEach(customer -> { // 模拟处理逻辑 }); } else { System.out.println("无权限访问该队列!"); } } // 其他通用方法(比如添加客户到自身队列)... }
然后创建两个子类,分别实现A和B的权限规则:
// Service A:仅允许访问Service B的队列 public class AService extends Service { @Override public boolean canAccessTargetQueue(Service target) { return target instanceof BService; } } // Service B:禁止访问Service A的队列 public class BService extends Service { @Override public boolean canAccessTargetQueue(Service target) { return !(target instanceof AService); } }
使用时直接实例化子类即可:
Service serviceA = new AService(); Service serviceB = new BService(); serviceA.processTargetQueue(serviceB); // 正常执行 serviceB.processTargetQueue(serviceA); // 被拒绝
优点:逻辑清晰,符合面向对象的多态设计,每个子类职责单一。
缺点:如果后续新增更多类型的Service,会导致类数量膨胀,适合当前只有A、B两种的简单场景。
2. 策略模式:解耦访问逻辑
如果不想创建太多子类,用策略模式把访问控制逻辑从Service类中抽离出来,通过给不同实例注入不同策略来实现行为差异,扩展性更强。
首先定义访问策略接口:
public interface QueueAccessStrategy { boolean isAllowed(Service own, Service target); }
然后实现两种策略:
// A的访问策略:允许访问B类型的Service public class AAccessStrategy implements QueueAccessStrategy { @Override public boolean isAllowed(Service own, Service target) { return target.getType() == Service.ServiceType.B; } } // B的访问策略:禁止访问A类型的Service public class BAccessStrategy implements QueueAccessStrategy { @Override public boolean isAllowed(Service own, Service target) { return target.getType() != Service.ServiceType.A; } }
修改Service类,持有策略对象并增加类型标记:
import java.util.ArrayList; public class Service { public enum ServiceType {A, B} private ServiceType type; private QueueAccessStrategy accessStrategy; protected ArrayList<Customer> waitingQueue; public Service(ServiceType type, QueueAccessStrategy accessStrategy) { this.type = type; this.accessStrategy = accessStrategy; this.waitingQueue = new ArrayList<>(); } public void processTargetQueue(Service target) { if (accessStrategy.isAllowed(this, target)) { // 处理队列逻辑 System.out.println("开始处理目标队列..."); } else { System.out.println("权限不足,无法访问!"); } } // Getter方法 public ServiceType getType() { return type; } }
使用时给不同实例注入对应策略:
Service serviceA = new Service(Service.ServiceType.A, new AAccessStrategy()); Service serviceB = new Service(Service.ServiceType.B, new BAccessStrategy()); serviceA.processTargetQueue(serviceB); // 正常执行 serviceB.processTargetQueue(serviceA); // 被拒绝
优点:扩展性极强,后续新增Service类型只需要新增策略类,无需修改Service本身,符合开闭原则。
缺点:需要额外定义接口和策略类,代码量略增,但对长期维护非常友好。
3. 实例状态标记:快速极简实现
如果你的场景非常简单(只有A、B两个实例),可以直接在Service类中加类型标记,在方法里判断自身和目标的标记来控制行为,无需额外类。
import java.util.ArrayList; public class Service { public enum ServiceType {A, B} private ServiceType type; protected ArrayList<Customer> waitingQueue; public Service(ServiceType type) { this.type = type; this.waitingQueue = new ArrayList<>(); } public void processTargetQueue(Service target) { boolean hasPermission = false; // 直接根据类型判断权限 if (this.type == ServiceType.A && target.type == ServiceType.B) { hasPermission = true; } else if (this.type == ServiceType.B) { // B不能访问A的队列,可根据需求调整其他权限 hasPermission = target.type != ServiceType.A; } if (hasPermission) { // 处理队列逻辑 System.out.println("开始处理目标队列..."); } else { System.out.println("无权限访问该队列!"); } } }
使用时:
Service serviceA = new Service(Service.ServiceType.A); Service serviceB = new Service(Service.ServiceType.B); serviceA.processTargetQueue(serviceB); // 正常执行 serviceB.processTargetQueue(serviceA); // 被拒绝
优点:代码量最少,实现最快,适合临时的简单场景。
缺点:权限逻辑耦合在Service类中,后续需求变化(比如新增C类型)需要修改Service方法,不符合开闭原则。
总结一下:如果只是临时的两个实例,用第三种方法最快;如果未来可能扩展更多类型,优先选策略模式;如果想严格遵循面向对象继承思想,选第一种子类方案。
内容的提问来源于stack exchange,提问作者jonelearn

