Java中如何通过Relationship实现Feature的互联?
世界生成程序中Feature与Relationship的实现方案
核心数据模型重构
- 放弃每个Feature本地存储关系的方案,改为全局统一维护Relationship实例集合。每个Relationship是唯一数据源,包含
subject、predicate、object三要素,以及双向关系对应的反向谓词映射(比如rules对应反向谓词is ruled by)。 - Feature仅保留自身属性,如需查询关联关系,通过全局集合检索(或维护轻量的关联Relationship ID列表,避免冗余存储)。
关系约束与一致性保障
1. Predicate元数据定义
为每个谓词(如is married to、rules)定义元数据,明确以下规则:
- 方向类型:单向/双向
- 类型约束:主体、客体允许的Feature子类(比如
rules的主体必须是Person,客体必须是Settlement) - 实例数量限制:主体/客体对该关系的支持类型(Single/Multiple,比如
Settlement的is ruled by只能是Single实例) - 属性约束:关联前需满足的属性条件(比如
Person年龄≥18才能成为Settlement的ruler) - 反向谓词名:双向关系对应的反向谓词标识
2. 统一关系操作接口
封装createRelationship、removeRelationship等核心操作,在接口层处理所有一致性逻辑:
- 约束校验:创建关系前自动验证类型、实例数量、属性条件,不满足则拒绝创建
- 双向关系同步:创建双向关系时,自动生成对应的反向关系条目;删除关系时,同步移除反向条目
- 属性自动同步:关联成功后自动执行属性修改(如
is child of关系创建时同步姓氏);关系移除时反向恢复属性(如移除rules关系时清空Settlement的ruler字段)
迭代生成流程优化
调整原有流程,让关系操作完全通过统一接口执行:
- Feature生成阶段:仅生成基础随机属性,不处理任何关系逻辑
- 关系匹配阶段:
- 随机选择待关联的Feature和Predicate
- 通过统一接口校验约束,查找符合条件的已有Feature,或生成新Feature补充
- 调用接口创建关系,自动完成同步与属性修改
- 终止条件:达到预设的Feature数量、关系总数,或满足特定世界规则(如所有
Settlement都有ruler)
示例代码片段
// Predicate元数据类,定义关系规则 class Predicate { String name; boolean isBidirectional; Class<?> subjectType; Class<?> objectType; Cardinality subjectCardinality; // SINGLE/MULTIPLE Cardinality objectCardinality; BiPredicate<Feature, Feature> constraint; // 属性约束校验逻辑 String inversePredicateName; // 双向关系的反向谓词名称 } // 全局关系管理器,负责所有关系的创建、删除与查询 class RelationshipManager { private final Map<String, Predicate> predicateRegistry = new HashMap<>(); private final List<Relationship> relationships = new ArrayList<>(); // 创建关系的核心方法,内置所有校验与同步逻辑 public boolean createRelationship(Feature subject, String predicateName, Feature object) { Predicate pred = predicateRegistry.get(predicateName); if (pred == null) return false; // 校验类型约束 if (!pred.subjectType.isInstance(subject) || !pred.objectType.isInstance(object)) { return false; } // 校验主体的实例数量限制(SINGLE类型不允许重复关联) if (pred.subjectCardinality == Cardinality.SINGLE && relationships.stream().anyMatch(r -> r.subject == subject && r.predicate.name.equals(predicateName))) { return false; } // 校验属性约束(比如Person年龄是否达标) if (!pred.constraint.test(subject, object)) { return false; } // 创建并添加关系 Relationship rel = new Relationship(subject, pred, object); relationships.add(rel); // 处理双向关系,自动创建反向条目 if (pred.isBidirectional) { Predicate inversePred = predicateRegistry.get(pred.inversePredicateName); if (inversePred != null) { relationships.add(new Relationship(object, inversePred, subject)); } } // 执行属性同步逻辑 syncAttributes(rel); return true; } // 删除关系,同步处理反向关系与属性恢复 public void removeRelationship(Relationship rel) { if (relationships.remove(rel)) { // 删除双向关系的反向条目 if (rel.predicate.isBidirectional) { relationships.removeIf(r -> r.subject == rel.object && r.predicate.name.equals(rel.predicate.inversePredicateName) && r.object == rel.subject ); } // 恢复属性(比如清空Settlement的ruler) revertAttributes(rel); } } // 查询指定Feature的所有关联关系 public List<Relationship> getRelationsForFeature(Feature feature) { return relationships.stream() .filter(r -> r.subject == feature || r.object == feature) .collect(Collectors.toList()); } // 关系创建时的属性同步逻辑 private void syncAttributes(Relationship rel) { switch (rel.predicate.name) { case "is child of": ((Person) rel.subject).setLastName(((Person) rel.object).getLastName()); break; case "rules": ((Settlement) rel.object).setRuler((Person) rel.subject); break; // 扩展其他关系的同步逻辑 } } // 关系删除时的属性恢复逻辑 private void revertAttributes(Relationship rel) { switch (rel.predicate.name) { case "rules": ((Settlement) rel.object).setRuler(null); break; // 扩展其他关系的恢复逻辑 } } } // 基础Feature抽象类 abstract class Feature { // 基础属性(ID、名称等) } // Feature子类示例:Person class Person extends Feature { private String lastName; private int age; // Getters & Setters public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // Feature子类示例:Settlement class Settlement extends Feature { private Person ruler; // Getters & Setters public Person getRuler() { return ruler; } public void setRuler(Person ruler) { this.ruler = ruler; } } // Relationship实体类 class Relationship { Feature subject; Predicate predicate; Feature object; public Relationship(Feature subject, Predicate predicate, Feature object) { this.subject = subject; this.predicate = predicate; this.object = object; } } // 数量限制枚举 enum Cardinality { SINGLE, MULTIPLE }
内容的提问来源于stack exchange,提问作者Luke Burston
相关产品推荐
相关产品推荐

