我有一个java类,它执行一个检查,每次执行检查时我都要存储它,而不需要创建更多的示例我应该如何实现这一点?

niwlg2el  于 2021-06-29  发布在  Java
关注(0)|答案(0)|浏览(180)

抱歉,如果我的问题措辞怪异,但我真的不知道有没有更好的方式来描述我的问题没有使用更多的词和显示我的代码。
这是一个设计问题,首先我将更详细地解释它,然后提供一些代码。我的java程序的结构如下:
我有一个类itemsfile,它本质上是一个从我的程序使用的文件中读取的类,并从文件中返回一个列表(项)。我的主类中有一个itemsfile类的最后一个示例。我有另一个类,叫做inventorychecker,它依赖于从itemsfile获取的项目列表。还有其他几个类依赖于我拥有的itemsfile对象的示例,我将其传递给它们的构造函数。还有其他依赖inventorychecker的类,在初始化itemsfile之后,我还在main中创建一个示例,然后将其作为参数传递。
inventorychecker的作用基本上是这样的:它有一个名为checkinventory(inventory)的函数,该函数接受库存,并检查库存是否包含itemsfile中列出的任何项目,如果是,则该方法返回true。
问题是:我有一个不断循环的清单,当我有一个清单导致checkinventory返回true时,它会不断地这样做,并且一遍又一遍地记录相同的事情,这会淹没我的日志文件。我只想让它再次记录,如果有什么非常不同的库存,如一个不同的项目,在itemslist中找到它。它实际上不需要从文件中读取数据就可以做到这一点,如果它在程序重新启动后再次记录相同的资源清册是完全正确的,并且因此日志文件中存在重复的资源清册。
下面是我想到的解决方案:
1.)我可以在inventorychecker类中创建一个静态hashmap,如果最终有多个inventorychecker示例,它将在所有inventorychecker示例中保持不变,基本上只需添加所述库存的所有者(将所有者想象成游戏中的玩家,他可能有一个库存,播放器是所述库存的所有者)作为键,找到的项目作为值(在某种容器中),然后每次运行checkinventory方法时,我都会查看播放器是否已经在其中-如果是这样,如果库存没有更改,我不会返回true。
这种方法的优点是它很容易实现,目前可能运行得很好,但缺点是我以后会有几个清单,对于其中一个清单,我希望这种行为有点不同(如果清单中的任何内容发生变化,它可能会返回true,不仅是如果有更多的违禁品,或者它甚至只是返回真的每一次)。
2.)更改inventorychecker,以便为每个inventorychecker创建一个新的inventorychecker对象,并向其添加一个compareto方法,然后在其他位置创建一个列表,其中添加返回true的inventorychecker的每个示例。然后,每当一个新的inventorychecker返回true时,我就可以遍历该列表并使用compare方法来查看它们是否相等,如果相等,我就不添加它,如果不相等,我就添加它。
这似乎是一种不好的方法,因为这将创建大量的对象,更不用说inventorychecker对象是在其他类中生成的,但是inventorychecker需要itemfile的项列表,这将是另一个问题,因为我必须将itemfile的示例放入所有使用inventorychecker的类中-可能使它们依赖于它,而我根本不喜欢这个方法。我真的不知道是否有任何赞成这种方法,但我只是认为这是一种可能性,也许我还没有意识到一些东西,使这种方法好。
这两种方法似乎都有一些问题,我对这两种方法都不是很喜欢。
这是我现在的代码:
main.java文件:

public class Main extends JavaPlugin{

    //filename of the yml file that contains all of the materials and quantities
    final String itemsYmlFileName = "items.yml";
    //file that stores the items to be used all throughout this plugin
    final ItemsFile itemsFile = new ItemsFile(this, itemsYmlFileName);

    /*
     * This function executes when the plugin is loaded/enabled,
     * due to the server starting, after a restart, or after a
     * plugin reload, etc.
     */
    @Override
    public void onEnable() {
        //this will be the inventoryChecker object passed to ContainerScanner and playerScanner. It's
        //best to get this here because it can be initialized with the itemsFile
        InventoryChecker inventoryChecker = new InventoryChecker(itemsFile);

        //register containerScanner event because it uses InventoryCloseEvent from bukkit.
        getServer().getPluginManager().registerEvents(new ContainerScanner(inventoryChecker), this);

        //Register PlayerScanner as a bukkit task so that it will execute the run() function on 
        //regular intervals. This is a synchronous task.
        @SuppressWarnings("unused")
        BukkitTask playerScan = new PlayerScanner(inventoryChecker).runTaskTimer(this, 500L, 100L);

        //set AddItem as the executor for this command so that it's onCommand() function is used
        //when a player types a command.
        this.getCommand("addItem").setExecutor(new AddItem(itemsFile));
    }

    /*
     * This function executes when the plugin is disabled due to
     * the server shutting down, restarting, reloading plugins, etc.
     */
    @Override
    public void onDisable() {
        //save any changes to the items Yml file
        itemsFile.saveFile();
    }
}

inventorychecker.java文件:

public class InventoryChecker {

    private HashMap<Material, Integer> itemList;

    //prevent default constructor from being used:
    @SuppressWarnings("unused")
    private InventoryChecker() {}

    /*
     * This constructor accepts a items file object, and will use that to read the Yml file that
     * contains all of the items and quantities to check for, and that will be used to check
     * inventories.
     */
    public InventoryChecker(ItemsFile itemsFile) {
        itemList = itemsFile.getItemsList();
    }

    /*
     * This constructor accepts a hashmap of Materials and Integers. The keys in this map
     * (materials) will be what the inventorychecker will check for in the inventory. The
     * values (integers) in this map will be the quantities that set off alerts. 
     */
    public InventoryChecker(HashMap<Material, Integer> items) {
        itemList = items;
    }

    /*
     * This function checks the inventory passed as a parameter to see if it contains any
     * materials over the set quantities, and returns true if so. The materials and quantities
     * to check for were passed during construction either as a itemsfile or a regular HashMap.
     */
    public boolean checkInventory(Inventory inv) {
        //cannot check inventory if it is null
        if(inv == null)
            return false;

        //tally all of the items in the inventory, and put them in the hashmap
        HashMap<Material, Integer> inventoryItems = tallyItems(inv);

        //loop through every entry in the itemList (hashmap of items to be checked)
        //and see if the player has any of the materials in a quantity that is 
        //greater than the value set in the config file
        for(Entry<Material, Integer> itemListEntry : itemList.entrySet()) {
            //this will be equal to null if the item is not in their inventory
            Integer i = inventoryItems.get(itemListEntry.getKey());

            //if it's equal to null, go on to the next item
            if(i == null)
                continue;

            //if an item is found, return true, they have a material in greater
            //quantity than listed in the config file.
            if(i > itemListEntry.getValue())
                return true;            
        }

        //return false, nothing was found
        return false;
    }

    /*
     * This function will accept an Inventory, and it will return a HashMap containing
     * each unique material found in the inventory as the keys, and the total amount of
     * the material in the inventory as the value:
     */
    private HashMap<Material, Integer> tallyItems(Inventory inv){
        //omitted to shorten post
    }
}

java(依赖于inventorychecker,这个类扫描玩家列表并检查每个清单。这是我上面提到的清单,我不想不断地重复记录同一个玩家):

public class PlayerScanner extends BukkitRunnable{

    private InventoryChecker inventoryChecker;

    //prevent usage of the default constructor, this class depends on
    //a valid InventoryChecker being passed
    @SuppressWarnings("unused")
    private PlayerScanner() {}

    public PlayerScanner(InventoryChecker inventoryChecker) {
        this.inventoryChecker = inventoryChecker;
    }

    @Override
    public void run() {
        for(Player player : Bukkit.getOnlinePlayers()) {
            //get their inventory/echest and have the inventorychecker
            //see if there are any suspicious quantities of materials in it
            boolean inv = false;
            boolean ender = false;
            inv = inventoryChecker.checkInventory(player.getInventory());
            ender = inventoryChecker.checkInventory(player.getEnderChest());

            if(inv || ender) {
                utility.sendAlertMessage("Player: " + player.getName() + "has illegal items in their Inventory or Echest!");
            }
        }
    }
}

containerscanner.java-另一个使用inventorychecker的类,除了这个之外,它是一个eventhandler,它基本上只是在播放器关闭容器时运行onclose()方法,然后检查该容器的库存:

public class ContainerScanner implements Listener{

    private InventoryChecker inventoryChecker;

    //disable default constructor
    @SuppressWarnings("unused")
    private ContainerScanner() {}

    public ContainerScanner(InventoryChecker inventoryChecker) {
        this.inventoryChecker = inventoryChecker;
    }

    /*
     * this runs any time the InventoryCloseEvent is triggered, and it
     * scans that inventory
     */
    @EventHandler(priority = EventPriority.MONITOR)
    public void onClose(InventoryCloseEvent e) {

        //if it was an ender chest, don't check because ender chests will be scanned
        //regularly with the player's inventory.
        if(e.getInventory().getType().equals(InventoryType.ENDER_CHEST))
            return;

        //send inventory to get checked
        inventoryChecker.checkInventory(e.getInventory());
    }
}

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题