2011-12-04 7 views
5

私は3つのクラス、抽象的なユーザと2つの特定のものを持っています:異なる(国内、国際、カスタムなど)可能な1つ以上のAddressオブジェクトのArrayListを保持するNormalUser trueを返すメソッドを持つAdminクラス。彼らはどちらもお互いに無関係なより多くのメソッドを含んでいます。私は、例えば次のように4ユーザーオブジェクトを作成する場合は、別のクラスの今 Java継承とinstanceofの定数使用を避ける

abstract class User{ 
    public User(String username, String pw){ 
... 

} 

public class NormalUser extends User{ 
... 
    private ArrayList<Address> addresses; 

... 

    public void addAdress(ArrayList<Address> address){ 
     addresses.addAll(address); 
} 

public class Admin extends User{ 

... 
    public boolean getIsAdmin(){ 
     return true; 
    } 
} 

ArrayList<User> users; 

    users.add(new NormalUser("1", "pw"); 
    users.add(new NormalUser("2", "pw"); 
    users.add(new NormalUser("3", "pw"); 
    users.add(new NormalUser("4", "pw"); 
    users.add(new Admin("5", "pw")); 
    users.add(new NormalUser("6", "pw"); 

そして、私はNormalUserでaddAddressメソッドを使用したいと言う、私はにspecficユーザーをダウンキャストする必要がありますNormalUserへのユーザー、私はこのようなNormalUserでaddAddressメソッドを使用する前に:

私はNormalUserと管理者の両方がユーザーになりたい理由は、私はそれらを処理することができそうです

 if (user instanceof NormalUser){ 
     NormalUser normal = (NormalUser) user; 
     normal.addAddress(...) 
     } 
一緒にログインするとき。

UserクラスにaddEmailを追加し、それをNormalUserクラスで上書きすることを考えましたが、NormalUserクラスのすべてのメソッドに対してこれを行う必要があります。さらに、Adminはそれをユーザーがその機能を必要としないときも同様です。

質問1:instanceofの使用が悪いと聞いたので、これを行うには良い方法がありますか? NormalUserクラスに固有のメソッドを使用するたびにinstanceofを使用する必要があります。

Quesiton 2:オブジェクトアドレスのArrayListは、RegularUserを特定のアドレス/(オブジェクト)にリンクする最適な方法ですか?

現在データベースはありません。ユーザCは、国内およびなど

おかげカスタムアドレスを持っている、

ですから、例えば、ユーザAが2つのアドレス国内1および国際的なものを持っており、ユーザBは、単に国内のアドレスを持っています。

PS。以前の投稿を広範囲に検索しましたが、解決策が見つかりませんでした。どちらのJavaの本でも、どちらもinstanceofの使用例を示していますが、悪いことは言及されていません。

+0

この具体的なケースについては、私は本当にどちらが良いかは言えませんが、「instanceof」は定義上悪いことではありません。多型性がより適切な場合には、それを過度に使用すべきではありません。 –

+0

'instanceof'に関連する:基本的な' User'で 'addAddress'を呼び出さないようにデザインを考え直すべきです。 'NormalUser'のために特別に設計されたコードブロックにいるときだけ、このようなメソッドを呼び出すべきです。 – toto2

+0

アドミニストレーターにアドレスがないのはなぜですか? – soulcheck

答えて

3

Visitor patternを使用することができます。ちょっとぎこちなく、少し読めないかもしれませんが、おそらくあなたの問題に最適な解決策です。

実際、addEmailを基底クラスにプッシュするソリューションはそれほど悪くありません。ベースUserの空の実装を提供し、RegularUserをオーバーライドするだけです。 Userインスタンスで電子メールの追加がサポートされているかどうかを確認する場合は、supportsAddEmailのような別の方法を指定してください。addEmailを無効にすると、falseが返され、trueが返されます。

+0

しかし、アドインを継承することはありません(たとえ空であっても)? – Brah

+0

はい、何もしない(何もしない) 'Admin.addEmail()'を呼び出すことができます。それが私が 'supportsAddEmail'を提案する理由ですが、実際には良い考えのようには見えません。ビットはこれがまさにあなたが望むものではありませんか?ユーザーが 'NormalUser'の場合は電子メールを追加し、そうでなければ何もしません。 –

+0

基本クラスに 'addEmail'を追加するのはいい考えですが、無害です。そのノーオペレーションについては、「誰かが管理対象オブジェクトに電子メールアドレスを伝えています。管理者が気にしないなら、それもそうです」と考えることができます。もしあなたが 'getEmail()'を基本クラスに入れなければならないのは醜いところです。この場合、特定の実装は例外をスローする必要があります。これは醜いものです。これを行う場合は、少なくとも 'supportsGetEmail()'のようなメソッドがあります。最善ののは、コールサイトがどのユーザサブクラスを持っているかを知っている場合です。したがって、 'getEmail()'をNormalUserにだけ追加することができます。 – yshavit

0

私は最も簡単な解決策は、NormalUserのリストとAdminのリストを含むクラスのUserListを作成することだと思います。 UserListクラスのインスタンスは、元のリストを置き換えます。クラスのUserListはいくつかの方法のような提供することができます:

  • ユーザーのgetUser(インデックスi)//二つのリストで実装

  • ユーザーはremoveUser(インデックスi)//二つのリストを用いて実装を

  • NormalUser getNormalUser(インデックスi)//通常のユーザーリスト
  • NormalUser removeNormalUser(インデックスi)//通常のユーザーリスト
  • 管理GETADMIN(インデックスi)で実装して実装//実装adminユーザーリスト
  • 管理removeAdmin(インデックスi)で// adminユーザーリスト
  • ....

適切なリストを処理するためのすべてのコードはのUserListクラスにカプセル化されるだろうと実装。ユーザーが何をする必要があるかに応じて、両方のリストまたは1つのリストのみを使用するメソッドを持つことができます。 UserListと対話するクラスは、UserList内に1つまたは2つのリストしかないかどうかを知りません。

+0

Philさんにお返事ありがとうございました。リストを保持するだけで新しいクラスを作成する必要はありませんでしたが、それは私にとっては良い考えです。私はJavaで新しいですが、例えば私は動物のスーパークラス、その後猫と犬のサブクラスを持っていた。私が犬と猫の動物のリストを持っていて、犬にbark()と呼んでいたければ、その犬のリストを作成しなければなりませんでしたか? - ちょうど私に直観的なようです:/ – Brah

+0

こんにちは。私があなたのところにいたら、(1)猫のリストと(2)犬のリストを作成します。あなたは10000匹の犬と10000匹の猫を持っていると考えてください。リストを分離すると、すべての犬を見つけるのがずっと速くなり、20000個の動物が混在した単一のリストがあるとすれば、犬を見つけることはずっと速くなります。 bark()などのメソッドを呼び出す必要がある場合は、bark()を呼び出す前に、20,000個の動物を処理する代わりに、犬のリストを処理し、犬か猫かをチェックするだけです。多くの要素がある場合、パフォーマンスは2つのリストではるかによくなるはずです。 – Phil