【问题标题】:Java: How can an 'agent' object that is inside a 'world' object obtain information about the 'world'?Java:“世界”对象内部的“代理”对象如何获取有关“世界”的信息?
【发布时间】:2015-06-01 14:29:35
【问题描述】:

很抱歉这个问题的措辞有点疯狂,但我对面向代理的思维很陌生(这些是“模式”吗?)而且对 java 的新意稍差一些,而且我正在努力解决这种感觉。非常基本的问题。

我在做很多这样的“直觉”(即盲目),而不是试图理解别人的代码 - 部分原因是我很难理解“高于我的水平”的代码,但也因为我希望这样做是“我的way' 将帮助我以后欣赏正确的方式。

基本上,我是在环境(房屋)中为代理(机器人真空吸尘器)建模。房屋包含房间的集合(HashMap)。 House 有一个方法getRoom(int key),它返回一个匹配给定键的 Room。代理有一个状态,此时它会跟踪房间 ID(这也是房子里的钥匙),这是机器人为了导航世界而“进入”的房间;状态还描述了房间是否已知是脏的。构建代理时,会使用 ID 对其进行初始化(必须在“房间内”创建),但不会给出房间的脏/干净状态。我希望代理检查污垢 - 这将涉及在 House 中调用 getRoom() 方法。但是,对于我到目前为止所学的 Java,我不知道该怎么做。我知道我可以通过在 java 中创建 House 或将方法设为静态来访问该方法,但这些方法不起作用 - 代理需要了解内存中的特定房子,即已使用 Rooms 初始化的房子.

tl;dr:Agent 对象如何获得对存储在另一个 Environment 对象内的 HashMap 中的对象的引用?

P.S 这是我设想的通过这种方法实现的“更高层次”视角的模型: 我直觉地希望代理对自己的规则和行为完全负责,这样更高层的代码看起来更像:

agent.percieve()                           //agent checks the room it thinks its in for dirt and exits
if (agent.gotDirt()) agent.clean()         //agent activates its cleaning device if it found dirt in this room
if (agent.gotDirt() == false) agent.move() //agent picks an exit and leaves the room

【问题讨论】:

  • 我意识到一种方法是在另一层(例如 World 或 Game)中执行有关更新代理状态和建模代理动作的逻辑,该层创建一个 House 对象和一个 Agent 对象,因此可以直接访问两者。我可能最终会这样做,但我想看看是否有其他方法
  • 第一个答案非常适合我的情况,但this question 在我实际理解此处发挥作用的按引用传递与按值传递困境方面帮助很大.该问题的最佳答案之一参考了this article,它的帮助更大。如果有人在尝试解决传递引用与传递值相关的类似问题时以某种方式到达这里,那么这些资源应该证明是无价的。

标签: java oop artificial-intelligence agent loose-coupling


【解决方案1】:

真空吸尘器(即您所谓的“代理”,但为什么要这样命名,因为它实际上是真空吸尘器?)只需要引用它所属的 House 对象:

// a single House is constructed
House house = new House(); 
// omitted: add rooms to the house...

// create a first vacuum cleaner for the house. A reference to the house is given to this cleaner
VacuumCleaner vacuumCleaner = new VacuumCleaner(house);
System.out(vacuumCleaner.isRoomClean(2)); // prints false, because room 2 is full of dirt
vacuumCleaner.cleanRoom(2);
System.out(vacuumCleaner.isRoomClean(2)); // prints true, because the vacuum cleaner removed the dirt from room 2

// now let's create a second vacuum cleaner for the same house
VacuumCleaner vacuumCleaner2 = new VacuumCleaner(house);
System.out(vacuumCleaner2.isRoomClean(2)); // prints true, because room 2 has no dirt: it has previously been removed from the room by the first vacuum cleaner.

编辑

以下是 VacuumCleaner 类的外观:

public class VacuumCleaner
    /**
     * The house that this vacuum cleaner cleans 
     */
    private House house;

    public VacuumCleaner(House houseToClean) {
        this.house = houseToClean;
    }

    public boolean isRoomDirty(int roomId) {
        // find the room in the house, and see if it contains dirt
    }

    public void cleanRoom(int roomId) {
        // find the room in the house, and remove dirt from it
    }
}

【讨论】:

  • 唯一的问题是我希望房子独立于真空而存在,例如以便同一房屋内可能存在多个真空吸尘器,或者特定真空吸尘器可能具有有关房屋的不正确信息(以及发现和处理该案例的适当方法)。同时,我不希望真空行为成为房屋的责任(例如,在房屋对象内创建真空,并在房屋中使用方法来更新真空的状态并确定行为等)。
  • 所以基本上,我正在尝试创建(有意的)冗余:世界存在,然后真空必须“探索”(从 House 对象发送和接收消息)以创建自己的内部该世界的模型 - 类似于物理机器人在真实房屋中的行为方式。
  • 再次阅读代码。房子对吸尘器一无所知。情况正好相反:真空吸尘器知道房子。你可以完美地为同一所房子创造另一个真空吸尘器。
  • 您将一个 reference(如果您愿意,是一个指针)传递给一个房子给真空吸尘器的构造函数,以便真空吸尘器保留这个 reference 到房子。没有复制。用同一个房子建造的两个真空吸尘器都引用了同一个房子。因此,如果一个人打扫这所房子的房间,另一个人会认为房间很干净。
  • 查看我的编辑。 Java 中永远不会传递对象。传递对象的引用。因此,主代码中的变量housevacuumCleaner 中的字段housevacuumCleaner2 中的字段house 是对同一个House 对象的三个引用,由new House() 创建。
猜你喜欢
  • 2016-06-16
  • 1970-01-01
  • 2013-02-12
  • 2021-03-24
  • 2013-02-04
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
相关资源
最近更新 更多