2016-04-09 10 views
1

今日、私はinstanceofの使用を避けることについてthis articleを読んでいます。 これは私には絶対に意味があります。私もvisitor patternを知っています。エンティティで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); 
    } 

} 
+0

メソッドのコードを... no codeに置き換える必要があります。それは何もしません。どのようなことをしているのかわからなくても、このメソッドを実装する方法をアドバイスできますか?とにかく、あなたが多型性、および訪問者のパターンを知っているなら、あなたはあなたが望むものを実装することができます。 –

+0

一般に、各クラスの操作を、Employeeクラスの抽象メソッドとして実装または定義されているメソッドに移動する方法があります。いくつかのことについては、これはお勧めできませんが、何をしようとしているのかわからなければ、その点についての入力はできません – romeara

+0

ごめんなさい。従業員のタイプに応じていくつかの計算を行いたいと仮定しましょう。編集された質問 –

答えて

1

はVisitorパターンを使用した簡単な例です。あなたのクラスがエンティティであるという事実は無関係です。重要なことは、基本クラスに固定されたよく知られた数のサブクラスがあることです。

は抽象クラスで始まるのをしてみましょう:

public abstract class Employee { 
    public abstract void accept(EmployeeVisitor visitor); 
} 

それは引数として訪問者を取る受け入れる()メソッドが含まれています。すべてのサブクラスはこのメソッドをオーバーライドする必要があります。今

2つのサブクラス、各フィールドとメソッドの明確なセットを持つ:

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 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); 
    } 
} 

が、中:

public interface EmployeeVisitor { 
    void visit(EnglishEmployee employee); 
    void visit(FrenchEmployee employee); 
} 

そして、ここでは、instanceofはの使用に比べて、それの使用例である:それは、各サブクラスの具体的な何かをするインタフェースですHibernateエンティティの場合は、実際には非常に便利です。なぜなら、Hibernateは遅延結合のために動的なプロキシを使用するからです。だから従業員は英語職員でもフランス人職員でもないかもしれません。その場合、instanceofはどちらの場合もfalseを返し、コードは何もしません。訪問者は、プロキシがラップしたフランス語または英語の従業員にコールを委任しますが、すべてがスムーズに行われます。

さらに、SpanishEmployeeを追加すると、スペイン語の従業員を処理するために変更する必要があるすべての訪問者の実装がすぐに表示されます。

0

一つの可能​​なトリックが行く:ここ

public abstract class Employee { 
    // ... 

    FullTimeEmployee asFullTimeEmployee() { 
     return null; 
    } 

} 

public class FullTimeEmployee extends Employee { 

    // ... 

    @override 
    FullTimeEmployee asFullTimeEmployee() { 
     return this; 
    } 

} 
関連する問題