Java:关于如何从基类继承工厂方法的最佳实践

时间:2014-02-04 15:24:05

标签: java inheritance parent-child factory-pattern

我正在创建一组类来表示旧数据库中的各种数据。我没有在构造函数内部使用异常来表示错误情况,而是决定使用工厂方法来创建各种对象。但是,我试图找出在继承这些类时如何最好地重用其中一些工厂。我正在寻找一个概念性的解释(即:最佳实践陈述你应该做的......)而不是一个实际的代码示例(尽管代码示例总是受欢迎的)。

例如,假设我有一个名为User的类,其中包含createUser工厂方法。我还有另一个名为Employee的类,它扩展了User类。如何从createEmployee方法重用(即:调用)createUser方法中的所有代码,以便它填充从User类继承的所有Employees字段?

明显的“解决方法”是将Employee类更改为具有User类而不是扩展它,但这与正常的OO原则不一致。

3 个答案:

答案 0 :(得分:1)

您可以使用其他initializeUser(用户用户)方法填充所有字段。 createUser创建一个新用户并使用它调用initializeUser。 createEmployer创建一个新的Employer并调用initializeEmployer,它调用initializeUser然后添加它的Employer东西。

要使外部用户不可见,请声明两个保护的initalize方法,以便它们仅在包内可见。另一种设计是拥有一个自己的工厂类,它包含所有的创建和初始化方法。

答案 1 :(得分:0)

尝试找到对您正在进行的问题进行建模的最佳方法,并且不要挂断标记您正在做的事情。

例如,您希望有两个类,User和Employee,以及Employee extends User。

在某些课程中,你有getUser和getEmployee。

在getEmployee中,您实例化Employee,然后只填充用户的值。这是我认为你被卡在标签上的地方。

我会有一个DAO(数据访问对象)类,我在其中放入了实际进入数据库的逻辑。所以,我有一个UserDAO和EmployeeDAO。

UserDAO只知道如何使用EmployeeDAO填充User对象,因此EmployeeDAO会执行以下操作:

Employee getEmployee(String id) {
  Employee emp = new Employee();
  User u = UserDAO.getUser(id);
  // either populate values or pass in the Employee since it can be a User class, to be populated.
  // get employee values
  return emp;
}

代码段帮助我整理自己的想法。因此,您可以传入Employee实例,并从User填充它,或者只是将值复制到自己身上。

但是,这可以保持逻辑分离,并允许您进行更灵活的设计。

答案 2 :(得分:0)

我会这样做的方式会是这样的。我会为User及其所有专用子类创建一个多态 init()方法,必要时(例如,你的Employee的init()方法只需要调用super方法)。然后我创建一个单独的 Factory 类,它会吐出User(基类)的实例,无论是User还是Employee等等。在其 createInstance(insert params here) 方法中,我将根据参数创建User或Employee或您的专用实例,然后为您刚刚构建的实例调用init()方法。 那样,你将构建阶段与初始化分开(因为理论上每个类都应该能够在init()上做自己的烹饪)并且你可以在实例创建时继承遗留初始化如果这就是你想要的。

一些代码示例:

class User() {
    //... your fields and constructor here

    public void init() {
       //... do your User init here
    }
}

class Employee extends User {
    ...
    public void init() {
       super.init();
       // ... other init stuff if you want
    }
}

class UserFactory{
    // ...

    public User createInstance(UserType type, String name, ...) {
        User user;
        switch (type) {
            case UserType.EMPLOYEE: user = new Employee(name,...);
        //... your other cases here
        }

        // the important part
        user.init();
        return user;
    }
}