使用不同参数创建类似子类实例的方法

3

我目前正在学习Java。我有一个带有超类(IndexCard)的项目,其中包括两个子类(EmployeeIndexCard和CustomerIndexCard)。这两个子类非常相似,但它们因其实例变量而彼此不同,并且因此具有不同的构造函数。

以下是它们:

class EmployeeIndexCard extends IndexCard {
    public WorkArea workArea ;
    protected String password;

    public employeeIndexCard(String name, String password, String adress, String phone, String email, String workArea) {
        super(name, adress, phone, email);
        this.password = password;
        this.workArea = WorkArea.valueOf(workArea);
    }
}


class CustomerIndexCard extends IndexCard {
    public customerIndexCard(String name, String adress, String phone, String email) {
        super(name, adress, phone, email);
    }
}

我想知道我做错了什么,因为为了创建这些类的实例,我创建了两个非常相似的方法:

/**
 * Create an instance of EmployeeIndexCard.
 */
public static void employeeIndexCard(String name, String dni, String password, String adress, String phone, String email, String workArea) {
    if (Utils.validateDni(dni) && !IndexCard.list.containsKey(dni)) {
        IndexCard.list.put(dni, new EmployeeIndexCard(name, password, adress, phone, email, workArea));
    } else {
        throw new InvalidParameterException();
    }
}

/**
 * Create an instance of CustomerIndexCard.
 */
public static void customerIndexCard(String name, String dni, String adress, String phone, String email) {
    if (Utils.validateDni(dni) && !IndexCard.list.containsKey(dni)) {
        IndexCard.list.put(dni, new FichaCliente(name, adress, phone, email));
    } else {
        throw new InvalidParameterException();
    }
}

有没有办法重新组织代码,将这两个几乎相同的方法合并起来?

4
首先,请不要用大写字母给一个方法命名,这会造成混淆。请使用类似小写字母的方式来命名方法。 - Ben
1
你为什么需要那些方法呢?直接将验证移到构造函数中不就好了。 - Kayaman
@Kayaman 如果我把验证移到构造函数中,那么它不还是重复的代码吗? - juan fran
1
你可以将公共部分放在超类构造函数中。现在,你可以使用构造函数(其中它们不会被验证)或者使用你创建的那些方法来创建对象。 - Kayaman
2个回答

2

由于你的两个类共享一个父类,重构代码最自然的方法是将创建实例的责任留给调用者,并接受任何IndexCard类型的实例:

public static void addIndexCard(String dni, IndexCard indexCard) {
    if (Utils.validateDni(dni) && !IndexCard.list.containsKey(dni)) {
        IndexCard.list.put(dni, indexCard);
    } else {
        throw new InvalidParameterException();
    }
}

这样,您可以简单地调用它:
//add customer index card:
addIndexCard("dni", new FichaCliente(name, adress, phone, email));

//add employee index card:
addIndexCard("dni2", new EmployeeIndexCard(name, password, adress, 
             phone, email, workArea));

1
问题是,从我的角度来看,你在违背面向对象设计。你没有提供对类IndexCard的访问,但它应该看起来像这样:
public class IndexCard {

    public static Map<String, IndexCard> map = new HashMap<>();

    private String name;
    private String address;
    private String phone;
    private String email;

    // constructor and accessors ommitted
}

首先,请勿使用public static字段,如果需要提供访问器。这可以防止其他类直接更改其状态。您还可以在此处放置验证逻辑:
public class IndexCard {

    private static Map<String, IndexCard> map = new HashMap<>();

    public static void addIndexCard(String dni, IndexCard card) {
        if (Utils.validateDni(dni) && !map.containsKey(dni)) {
            map.put(dni, card);
        } else {
            throw new InvalidParameterException();
        }
    }

    private String name;
    private String address;
    private String phone;
    private String email;

    // constructor and accessors ommitted
}

您可以像这样使用类:

IndexCard c1 = new EmployeeIndexCard(name, password, adress, phone, email, workArea);
IndexCard.addIndexCard("c1", c1);
IndexCard c2 = new FichaCliente(name, adress, phone, email);
IndexCard.addIndexCard("c2", c2);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接