Class1 имеет ArrayList, но у Class2 есть один экземпляр Class1? - PullRequest
0 голосов
/ 12 мая 2018

В моем проекте у меня есть класс Store, у меня также есть класс Manager.Теперь менеджер может управлять многими магазинами, но у магазина может быть один менеджер.Это приводит к:

МЕНЕДЖЕР-КЛАСС ХАС: ArrayList store;

STORE CLASS HAS: Менеджер-менеджер;

Мне нужно иметь возможность обратиться к менеджеру из магазина, номне также нужно получить все магазины у менеджера.

Так что мне нужно уметь это делать: manager.getStores ();& store.getManager ();

Это создает цикл создания новых экземпляров объекта и необходимость продолжать чтение из базы данных.Я не уверен, как это сделать как с точки зрения дизайна, так и с практической точки зрения, я все еще новичок в этом, так что если кто-то может мне помочь, это было бы удивительно!

Ответы [ 3 ]

0 голосов
/ 12 мая 2018

Существует только одна причина хранить ссылки в обоих направлениях: для производительности.Если вам не нужно хранить и искать большой объем данных, сохраняйте их как можно более простыми.

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();
        }
    }
}

Наконец, если вы действительно хотите сохранить ссылки в обоих направлениях, вам потребуется каждое обновление, чтобы автоматически изменять ссылку в другом направлении.Это общеизвестно, склонный к ошибкам подход.Как только ваша модель усложняется, становится легко обнаружить трудно обнаруживаемые повреждения ссылок (например, через подкласс, который переопределяет установщик без вызова установщика суперкласса).Избегайте этого, если можете.

0 голосов
/ 12 мая 2018

Вы можете попытаться использовать этот дизайн (или его вариант согласно вашей схеме) для построения двухстороннего отображения:

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
0 голосов
/ 12 мая 2018

В этом примере мы предположим, что таблица менеджеров имеет первичный ключ ID, а таблица магазинов имеет поле manager, которое ссылается на менеджеров ID.

Итак, SELECT ваши managers данные из БД, циклически просматривайте записи и создайте массив managers объектов.

Далее SELECT из вашей таблицы stores, цикл по этим записям начинает создавать массив объектов stores, и в этом цикле вы можете иметь вложенный цикл, чтобы пройти по массиву менеджеров и найти менеджера в хранилище. ссылка на объект / запись, затем установите этот менеджер для магазина и добавьте магазин в список магазинов менеджера.

//  Assume db_mgrs and db_stores are result sets return from database.
Object[][] db_mgrs = new Object[][]{{0, "Steve"}, {1, "Bob"}, {2, "Nick"}, {3, "Sam"}};
Object[][] db_stores = new Object[][]{{1, "First Store", 0}, {2, "Second Store", 0}, {3, "Third Store", 2}};

ArrayList<Manager> managers = new ArrayList<>();
ArrayList<Store> stores = new ArrayList<>();

for(int i = 0; i < db_mgrs.length; i++) {
    managers.add(new Manager((int)db_mgrs[i][0], (String)db_mgrs[i][1]));
}

for(int i = 0; i < db_stores.length; i++) {
    stores.add(new Store((int)db_stores[i][0], (String)db_stores[i][1]));
    for(int j = 0; j < managers.size(); j++) {
        if(db_stores[i][2].equals(managers.get(j).getId())) {
            stores.get(i).setMgr(managers.get(j));
            break;
        }
    }
}

for(int i = 0; i < stores.size(); i++) {
    System.out.println(stores.get(i).getMgrName());
}
...