How to organize OO design with two different types of users

I have two different types of users, and I have mapped them to the two Java classes UserWheel and UserSea , and they have a common abstract superclass of the User class . The data stored for these types of users is about the same, but the behavior is different.

Then I created an abstract class called UserCollection with derived classes UserWheelCollection and UserSeaCollection to find subordinates or load subusers.

Then I added an abstract method to the UserCollection class with a signature

public abstract List<User> listAllSubusers()

this is because the implementation will be different. Each Created User will be UserWheel or UserSea, depending on which method was called, but also the rest of the implementation is different.

Then I want to add a new method to UserCollection with the signature public UserloadById (int idUser) . In this case, the implementation will be the same, except for the fact that the returned user will be an instance of either UserWheel or UserSea . In this case, I am reluctant to use the abstract method in the base class due to code duplication.

I can test a specific UserCollection class with instanceof and create a corresponding subclass, but it does not look object oriented and violates the open-close principle.

- 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: , .

+3
3

, , . , interface ListSubUsersStrategy, interface CreateUserStrategy ..

. .

: . , listAllSubUsers() , . , , , .

:

A has wheel users.
B has sea users.
C has wheel users.

:

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

/** @see http://stackoverflow.com/questions/6006323 */
public class UserMain {

    private static final List<User> users = new ArrayList<User>();

    public static void main(String[] args) {
        users.add(new User("A", new WheelStrategy()));
        users.add(new User("B", new SeaStrategy()));
        users.add(new User("C", new WheelStrategy()));
        for (User user : users) {
            user.listAllSubUsers();
        }
    }

    private static class User {

        private String name;
        private SubUsersStrategy suStrategy;

        public User(String name, SubUsersStrategy suStrategy) {
            this.name = name;
            this.suStrategy = suStrategy;
        }

        public void listAllSubUsers() {
            System.out.print(name + " manages ");
            List<User> subUsers = suStrategy.getList();
        }
    }

    private interface SubUsersStrategy {

        List<User> getList();
    }

    private static class WheelStrategy implements SubUsersStrategy {

        @Override
        public List<User> getList() {
            System.out.println("wheel users.");
            return null;
        }
    }

    private static class SeaStrategy implements SubUsersStrategy {

        @Override
        public List<User> getList() {
            System.out.println("sea users.");
            return null;
        }
    }
}
+3

FWIW, Trashgod. , .

public interface UserStore<T extends User> {
    public T create(int id);
    public List<T> listAll();
}

public class SeaUserStore implements UserStore<SeaUser> {
    public SeaUser create(int id) { return new SeaUser(id); }
    public List<SeaUser> listAll() { whatever }
}

// the dry counterpart of 'sea' is either 'land' or 'road', not 'wheel' :)
public class RoadUserStore implements UserStore<RoadUser> {
    public RoadUser create(int id) { return new RoadUser(id); }
    public List<RoadUser> listAll() { whatever }
}

public class UserCollection<T extends User> {
    private UserStore<T> store;
    public UserCollection(UserStore<T> store) {
        this.store = store;
    }
    public List<T> listAll() {
        return store.listAll();
    }
    public T getById(int id) {
        T user = store.create(id);
        // populate
        return user;
    }
}

UserCollection. ; UserCollection :

public class UserCollection<T extends User> {
    public static UserCollection<SeaUser> createSeaUserCollection() {
        return new UserCollection<SeaUser>(new SeaUserStore());
    }
    public static UserCollection<RoadUser> createRoadUserCollection() {
        return new UserCollection<RoadUser>(new RoadUserStore());
    }
}
+3

UserCollection instanceof , open-close.

, , , . , User , , CompledUser, DirtyUser . (, if check instanceof ..).

- "is-a", , , . , . - , .

Another idea is to add the abstract createNewUser () method to the UserCollection and specific implementations in subclasses to return a new instance, so the base class will just call this createNewUser () method

This is the best approach, as the caller, if he createNewUserdoes not care about which user he receives. All he knows is that he is a user.

The approach is called the factory method template.

+1
source

All Articles