Class1有ArrayList <class2>,但Class2有一个Class1实例?

时间:2018-05-11 23:22:14

标签: java class reference instance

在我的项目中,我有一个Store类,我也有一个Manager类。现在经理可以经理许多商店,但商店可以有一个经理。这导致:

经理人课程: ArrayList存储;

商店类别: 经理经理;

我需要能够从商店中引用经理,但我还需要从经理那里获得所有商店。

所以我需要能够做到: manager.getStores(); &安培; store.getManager();

这会创建一个创建新对象实例的循环,并且需要继续从数据库中读取。我不确定如何从设计和实践的角度来看待这个问题,我对此仍然很陌生,所以如果有人能帮助我,那就太棒了!

3 个答案:

答案 0 :(得分:0)

对于此示例,我们假设管理器表具有ID主键,而存储表具有引用管理器manager的{​​{1}}字段。

因此ID来自数据库的SELECT数据,遍历记录并构建您的managers对象数组。

来自managers表的下一个SELECT,循环遍历这些记录,开始构建您的stores对象数组,在此循环中,您可以使用嵌套循环来完成管理器数组找到商店对象/记录引用的经理,然后为商店设置该经理,并将商店添加到经理的商店列表中。

stores

答案 1 :(得分:0)

在两个方向上存储引用只有一个原因:性能。除非您需要存储和搜索大量数据,否则请尽可能简单。

class Store {
    private Manager manager;

    public Manager hasManager(Manager manager) {
        return this.manager.equals(manager);
    }
}

class StoreList {
    private final List<Store> stores;

    public Stream<Store> getManagedStores(Manager manager) {
        return stores.stream().filter(s -> s.hasManager(manager));
    }
}  

这会自动强制引用完整性,因为商店只能有一个管理器。它将关于商店管理的逻辑封装在商店列表中而不是管理器中。关于这一点的好处是Manager类不需要知道关于商店的任何内容:可以使用相同的类来管理餐馆而不做任何更改。

如果您确实需要getStores课程中的Manager,那么您需要实施一些验证:

class StoreList {
    public boolean hasStore(Store store) {
        return stores.contains(store);
    }
}

class Manager {
    private final StoreList stores;

    public boolean hasStoreInStoreList(Store store) {
        return stores.hasStore(store);
    }

    public Stream<Store> getStores() {
        return stores.getManagedStores(this);
    }
}

class Store {
    public void setManager(Manager manager) {
        if (manager.hasStoreInStoreList(this))
            this.manager = manager;
        else
            throw new IllegalArgumentException("Manager for different stores");
    }
}

如果性能是一个问题,那么常见的方法是使用缓存。这是一个很好理解的设计模式,涉及保留搜索结果的副本以避免重复搜索。如果引用更改,则会清除缓存,从而强制再次运行搜索。它可能看起来像这样:

class Manager {
    private Optional<List<Store>> managedStores = Optional.empty();

    public void purgeCache() {
        managedStores = Optional.empty();
    }

    public Stream<Store> getStores() {
        if (!managedStores.isPresent())
            managedStores = Optional.of(stores.getManagedStores(this)
                .collect(Collectors.toList()));
        return managedStores.get().stream();
    }
}

class Store {
    public void setManager(Manager manager) {
        if (!manager.equals(this.manager)) {
            this.manager.purgeCache();
            this.manager = manager;
            this.manager.purgeCache();
        }
    }
}

最后,如果您真的想要在两个方向上维护引用,那么您将需要每次更新以自动更改其他方向的引用。这是一种众所周知的容易出错的方法。一旦你的模型变得复杂,很容易让难以检测的参考腐败蔓延(例如,通过一个子类来覆盖setter而不调用超类的setter)。如果可以,请避免这种情况。

答案 2 :(得分:0)

您可以尝试使用此设计(或根据您的架构的变体)来构建双向映射:

<强> Store.class

public class Store {

    private Manager manager;
    private final String storeName;

    public Store(String storeName) {
        this.storeName = storeName;
    }

    public void setManager(Manager manager) {
        this.manager = manager;
    }

    public Manager getManager() {
        return manager;
    }

    public String getStoreName() {
        return storeName;
    }
}

<强> Manager.class

import java.util.ArrayList;
import java.util.List;

public class Manager {

    private List<Store> stores;
    private final String firstName;
    private final String lastName;

    public Manager(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public List<Store> getStores() {
        return stores;
    }

    public void assignStore(Store store) {
        if (stores == null) {
            stores = new ArrayList<>();
        }
        stores.add(store);
    }

    public String getFullName() {
        return firstName + " " + lastName;
    }
}

RetailCorp.class(构建映射):

import java.util.ArrayList;
import java.util.List;

public class RetailCorp {

    public static void main(String[] args) {

        //This is simulating list of managers from a data store
        List<Manager> managerList = getManagerData();

        //This is simulating list of stores from a data store. Each store has a manager assigned to it.
        List<Store> storeList = getStoreData(managerList);

        System.out.println("=== Now, look through each store and assign managers their list of stores");
        for (int i = 0; i < storeList.size(); i++) {
            Store currentStore = storeList.get(i);
            currentStore.getManager().assignStore(currentStore);
        }

        //Output stores and their managers
        showStoresAndTheirManagers(storeList);

        //Output managers and their stores
        showManagersAndTheirStores(managerList);
    }

    private static List<Manager> getManagerData() {
        System.out.println("=== Building manager data");
        List<Manager> managerList = new ArrayList<>();
        int totalManagers = 2;
        for (int i = 0; i < totalManagers; i++) {
            managerList.add(new Manager("FN-" + i, "LN-" + i));
        }
        return managerList;
    }

    private static List<Store> getStoreData(List<Manager> managerList) {
        System.out.println("=== Building stores data");
        List<Store> storeList = new ArrayList<>();
        int totalStores = 3;
        for (int i = 0; i < totalStores; i++) {
            storeList.add(new Store("Store " + i));
        }
        storeList.get(0).setManager(managerList.get(0));    //store 0 -> manager 0
        storeList.get(1).setManager(managerList.get(1));    //store 1 -> manager 1
        storeList.get(2).setManager(managerList.get(0));    //store 2 -> manager 0
        return storeList;
    }

    private static void showStoresAndTheirManagers(List<Store> storeList) {
        System.out.println("=== Print stores and their manager");
        for (int i = 0; i < storeList.size(); i++) {
            Store currentStore = storeList.get(i);
            System.out.println(currentStore.getStoreName() + " has Manager: " + currentStore.getManager().getFullName());
        }
    }

    private static void showManagersAndTheirStores(List<Manager> managerList) {
        System.out.println("=== Print managers and their stores");
        for (int i = 0; i < managerList.size(); i++) {
            Manager currentManager = managerList.get(i);
            System.out.println("Manager: " + currentManager.getFullName() + " has total " + currentManager.getStores().size() + " stores");
            currentManager.getStores().forEach(s -> System.out.println(s.getStoreName()));
        }
    }
}

运行输出

=== Building manager data
=== Building stores data
=== Now, look through each store and assign managers their list of stores
=== Print stores and their manager
Store 0 has Manager: FN-0 LN-0
Store 1 has Manager: FN-1 LN-1
Store 2 has Manager: FN-0 LN-0
=== Print managers and their stores
Manager: FN-0 LN-0 has total 2 stores
Store 0
Store 2
Manager: FN-1 LN-1 has total 1 stores
Store 1