java – 如何使用两种不同类型的用户组织OO设计

我有两种不同类型的用户,我将它们映射到两个 Java类UserWheel和UserSea,它们有一个名为User的公共抽象超类.为这些用户类型保存的数据大致相同,但行为不同.

然后我创建了一个名为UserCollection的抽象类,其派生类UserWheelCollection和UserSeaCollection用于搜索用户或加载子用户.

然后我添加一个带签名的UserCollection类的抽象方法

public abstract List<User> listAllSubusers()

这是因为实施会有所不同.创建的每个用户将是UserWheel或UserSea,具体取决于调用方法,但实现的其余部分完全不同.

然后我想用签名公共用户loadById(int idUser)向UserCollection添加一个方法.在这种情况下,实现将是相同的,除了用户返回的事实将是UserWheel或UserSea的实例.在这种情况下,我不愿意在基类中使用抽象方法,因为代码重复.

我可以使用instanceof检查UserCollection的具体类,并创建一个合适的子类,但它似乎不是面向对象的,并打破了开放原则.

一个想法是将一个抽象方法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实际上是同一个类,唯一不同的是我分配给它们的行为.或者,我只能用setter编写一个类:

UserCollection userColl = new UserCollection();
userColl.setSubUserBehavior(new SubUserManagementSeaimplementation());
userColl.setCrudBehavior(new UserCrud());

但是初始化会很麻烦,特别是如果我有更多的行为类.那么我做错了什么?如何妥善组织?

更新2:我用我实现的设计写了一个blog post.

解决方法

不要继承行为,而是考虑使用 strategy pattern中的接口封装它.用户在使用接口ListSubUseRSStrategy,接口createuserStrategy等两个具体实现时会有所不同.

另见相关的bridge pattern.

附录:在下面的示例中,每个用户都有一个查找子用户的具体策略.特别是,listAllSubUsers()调用接口方法,自动分派到正确的具体实现.该模式并不能减轻您编写接口的具体实现,但它确实解耦了它们,确保更改它不会破坏另一个.

安慰:

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

码:

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

/** @see https://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;
        }
    }
}

相关文章

Java中的String是不可变对象 在面向对象及函数编程语言中,不...
String, StringBuffer 和 StringBuilder 可变性 String不可变...
序列化:把对象转换为字节序列的过程称为对象的序列化. 反序...
先说结论,是对象!可以继续往下看 数组是不是对象 什么是对...
为什么浮点数 float 或 double 运算的时候会有精度丢失的风险...
面试题引入 这里引申出一个经典问题,看下面代码 Integer a ...