У меня два разных типа пользователей, и я сопоставил их с двумя классами Java UserWheel и UserSea , и у них есть общий абстрактный суперкласс, называемый User . Данные, сохраненные для этих типов пользователей, примерно одинаковы, но поведение отличается.
Затем я создал абстрактный класс с именем UserCollection с производными классами UserWheelCollection и UserSeaCollection для поиска подпользователей или загрузки подпользователя.
Затем я добавил абстрактный метод в класс UserCollection с подписью
public abstract List<User> listAllSubusers()
это потому, что реализация будет отличаться. Каждый созданный пользователь будет UserWheel или UserSea, в зависимости от того, какой метод был вызван, но и все остальные варианты реализации весьма различны.
Затем я хочу добавить новый метод в UserCollection с подписью public User loadById (int idUser) . В этом случае реализация будет такой же, за исключением того факта, что возвращенный пользователь будет экземпляром UserWheel или UserSea . Я не хочу использовать абстрактный метод в базовом классе из-за дублирования кода.
Я могу проверить конкретный класс UserCollection с помощью instanceof и создать соответствующий подкласс, но он не кажется объектно-ориентированным и нарушает принцип открытия-закрытия.
Другая идея заключается в добавлении абстрактного метода createNewUser () к UserCollection и конкретных реализаций в подклассах для возврата нового экземпляра, поэтому базовый класс просто вызовет этот метод createNewUser ().
Как вы думаете, этот второй путь имеет смысл? Или вы бы организовали вещи по-другому и как?
UPDATE . Текущая ситуация:
abstract class User
public String getAddress()
public void setAddress()
...
class UserSea extends User
class UserWheel extends User
abstract class UserCollection
protected abstract User createNewUser();
public abstract List<User> listAllSubUsers();
public User loadById(int idUser) {
User newUser = createNewUser();
//populate it
return newUser;
}
class UserSeaCollection
protected User createNewUser() {
return new UserSea();
}
public List<User> listAllSubusers()
class UserWheelCollection
protected User createNewUser() {
return new UserWheel();
}
public List<User> listAllSubusers()
Я попытался понять шаблон стратегии, предложенный trashgod, и вот моя первая попытка:
interface SubuserManagement
List<User> listAllSubUsers();
...
interface UserCrud
void create();
User readById(int idUser);
void update();
void delete();
class UserSeaCollection implements SubUserManagement, UserCrud
private SubUserManagement subuserBehavior = new SubUserManagementSeaImplementation();
private UserCrud userCrudBehavior = new UserCrud();
void create {
subUserBehavior.create();
}
...
class UserWheelCollection implements SubUserManagement, UserCrud
...
class SubUserManagementWheelImplementation implements SubUserManagement
List<User> listAllSubUsers();
class SubUserManagementSeaImplementation implements SubUserManagement
List<User> listAllSubUsers();
class UserCrudImplementation implements UserCrud //only 1 implementation
void create();
User readById(int idUser);
void update();
void delete();
В этой первой попытке я создал UserCollectionWheel и UserCollectionSea, которые больше не используют общий суперкласс, но реализуют те же интерфейсы. Фактическая реализация находится во внешних классах.
Теперь UserCollectionWheel и UserCollectionSea - это действительно один и тот же класс, с единственным отличием в поведении, которое я им назначаю. В качестве альтернативы я мог бы написать только один класс с сеттерами:
UserCollection userColl = new UserCollection();
userColl.setSubUserBehavior(new SubUserManagementSeaImplementation());
userColl.setCrudBehavior(new UserCrud());
Но инициализация была бы громоздкой, особенно если бы у меня было больше классов поведения. Так что я делаю не так? Как правильно это организовать?
ОБНОВЛЕНИЕ 2 : я написал сообщение в блоге с дизайном, который я реализовал.