Java 避免将instanceof与实体一起使用
今天我读了一篇关于避免使用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
@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。但无论是否有实体,它都是完全相同的访问者模式。