Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 避免将instanceof与实体一起使用_Java_Oop - Fatal编程技术网

Java 避免将instanceof与实体一起使用

Java 避免将instanceof与实体一起使用,java,oop,Java,Oop,今天我读了一篇关于避免使用instanceof的文章。 这对我来说绝对有道理。我也意识到这一点 假设我有以下情况: @Entity public abstract class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer employeeId; private String name; } @Entity public class FullTi

今天我读了一篇关于避免使用instanceof的文章。 这对我来说绝对有道理。我也意识到这一点

假设我有以下情况:

@Entity
public abstract class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer employeeId;

    private String name;

}



@Entity
public class FullTimeEmployee extends Employee {

    protected Integer salary;

    public Integer getSalary() {
        return salary;
    }

    public void setSalary(Integer salary) {
        this.salary = salary;
    }
}
@Entity
public class PartTimeEmployee  extends  Employee{

    protected Float hourlyWage;

    public Float getHourlyWage() {
        return hourlyWage;
    }

    public void setHourlyWage(Float hourlyWage) {
        this.hourlyWage = hourlyWage;
    }
}
在调用这样的方法时,如何避免使用instanceof

    public void convertEmployee(Employee employee) {

    if (employee instanceof FullTimeEmployee) {
       FullTimeEmployee fullTimeEmployee = (FullTimeEmployee) employee;
       calcSalaray(fullTimeEmployee);


    } else if (employee instanceof PartTimeEmployee) {
        PartTimeEmployee partTimeEmployee = (PartTimeEmployee) employee;
        calcHourlywage(partTimeEmployee);
    }

}

一个可能的诀窍是:

public abstract class Employee {
    // ...

    FullTimeEmployee asFullTimeEmployee() {
        return null;
    }

}

public class FullTimeEmployee extends Employee {

    // ...

    @override
    FullTimeEmployee asFullTimeEmployee() {
        return this;
    }

}

下面是一个使用访问者模式的简单示例。类是实体这一事实与此无关。重要的是基类有固定的、众所周知的子类数量

让我们从抽象类开始:

public abstract class Employee {
    public abstract void accept(EmployeeVisitor visitor);
}
它包含一个accept()方法,该方法将访问者作为参数。每个子类都必须重写此方法

现在是两个子类,每个子类都有一组不同的字段和方法:

public class FrenchEmployee extends Employee {

    private int eiffelTowerVisits;

    @Override
    public void accept(EmployeeVisitor visitor) {
        visitor.visit(this);
    }

    public int getEiffelTowerVisits() {
        return eiffelTowerVisits;
    }
}


public class EnglishEmployee extends Employee {

    private int towerBridgeVisits;

    @Override
    public void accept(EmployeeVisitor visitor) {
        visitor.visit(this);
    }

    public int getTowerBridgeVisits() {
        return towerBridgeVisits;
    }
}
这位访客是什么?它是一个为每个子类执行特定操作的接口:

public interface EmployeeVisitor {
    void visit(EnglishEmployee employee);
    void visit(FrenchEmployee employee);
}
下面是一个it使用的示例,与instanceof的使用情况相比:

public class EmployeeService {

    public void displayEmployeeWithUglyInstanceof(Employee employee) {
        if (employee instanceof EnglishEmployee) {
            EnglishEmployee english = (EnglishEmployee) employee;
            System.out.println("An English employee that visited the tower bridge " + english.getTowerBridgeVisits() + " times");
        }
        else if (employee instanceof FrenchEmployee) {
            FrenchEmployee french = (FrenchEmployee) employee;
            System.out.println("A French employee that visited the eiffel tower " + french.getEiffelTowerVisits() + " times");
        }
    }

    public void displayEmployeeWithVisitor(Employee employee) {
        EmployeeVisitor visitor = new EmployeeVisitor() {
            @Override
            public void visit(EnglishEmployee employee) {
                System.out.println("An English employee that visited the tower bridge " + employee.getTowerBridgeVisits() + " times");
            }

            @Override
            public void visit(FrenchEmployee employee) {
                System.out.println("A French employee that visited the eiffel tower " + employee.getEiffelTowerVisits() + " times");
            }
        };

        employee.accept(visitor);
    }
}
您可能会认为这过于工程化,但对于Hibernate实体来说,它实际上非常有用,因为Hibernate使用动态代理进行惰性关联。因此,雇员很可能既不是英国雇员,也不是法国雇员。在这种情况下,
instanceof
在这两种情况下都将返回false,而您的代码不会做任何事情。而对于访客,代理将把呼叫委托给其包装的法国或英国员工,一切都会顺利进行


另一个优点是,如果您添加一名西班牙员工,您将立即看到所有必须修改以处理西班牙员工的访问者实现。

该方法的代码应替换为。。。根本没有代码。它没有任何作用。在不知道该怎么做的情况下,我们如何建议一种实现此方法的方法?无论如何,如果您知道多态性和访问者模式,那么您可以实现任何您想要的。通常,一种方法是将每个类的操作移动到一个方法中,该方法在Employee类上实现或定义为抽象方法。在某些情况下,这是不可取的,但在不知道您尝试执行什么操作的情况下,无法提供该操作的输入。抱歉,没有提供更多详细信息。假设我们想根据员工类型进行一些计算。见编辑的问题,这仍然是非常模糊的。如前所述,您只需在基类中添加一个抽象方法
calculatePay()
,并在两个子类中重写它(在一个子类中使用工资,在第二个子类中使用小时工资)。如果代码不能在实体中,并且必须调用包含
convertEmployee()
的类的方法,则使用访问者模式。@Codefella done。但无论是否有实体,它都是完全相同的访问者模式。