2015-12-09 9 views
5

私はクラスキャストで少し苦労しています。シーンを設定しましょう。私はサービスとオーケストレーター層を使用するJavaサーバーコードを持っています。要求は、Bean形式(フロントエンドビューに合わせたJavaクラス)のサービスレイヤーに入ってきます。次に、Beanフォーマットオブジェクトを取得し、それをドメイン形式オブジェクトに変換するdomainBeanMapperクラスの束があります。たとえば、UserBeanには文字列で表されるdateOfBirthがあり、UserにはDateOfBirthがDateで表されるため、UserMapper.javaは日付文字列を日付オブジェクトにします。したがって、システム内の各オブジェクトには、* .java、* Bean.java、* Mapper.java(User.java、UserBean.java、userMapper.java)があります。 ApplicationContextの中Java - インターフェイスにキャストし、キャストされたタイプが何であるかを調べる

私はこのように、彼らのマッパーへの各オブジェクトからの関係を保持する:

<util:map id="domainBeanMappers"> 
    <entry key="UserBean" value-ref="userMapper" /> 
    <entry key="User" value-ref="userMapper" /> 
..... 

、その後、私はマッパーを定義します。

<bean id="userMapper" class="com.me.mapping.UserMapper" parent="baseDomainBeanMapper"/> 

私はこのようなドメイン豆マッパーから呼び出します私のサービス層:

UserBean userBean = (UserBean) getDomainBeanMapper().mapDomainToBean(user); 

このコードを実行すると、私はマッパーobje私はこのようにしたいCT:findApplicableMapperはこのように動作します

DomainBeanMapper mapper = findApplicableMapper(myObject.getClass().getName()); 
    if (mapper == null) { 
     mapper = findApplicableMapper(myObject.getClass().getSimpleName()); 
    } 

:過去数年間

private DomainBeanMapper findApplicableMapper(String string) { 
    return domainBeanMappers.get(string); 
} 

が、これは魅力のように働いています。どのようなオブジェクトであれ、私は簡単に関連するマッパーを選択してから、どのインスタンスの.getClass()呼び出しに基づいて、自分のbean形式からドメイン形式に変換したり、その逆に変換することができます。

今、私は困っている新しい要件があります。私はUserオブジェクトからパラメータに基づいていくつかのサブオブジェクトに変換できるようにしたい。だから、いくつかの呼び出しでは、私はid、firstNameとlastNameだけ戻ってほしいです。他の呼び出しでは、より多くのフィールドを必要としますが、オブジェクト全体ではありません。いくつかの呼び出しでは、前と同じようにオブジェクト全体を元に戻します。私は、サブオブジェクトのパスを下って、UserLight、UserLightWithName、UserLightWithNameButNoAddress、... arghの悪夢で終わることは望んでいません。

代わりに、私は "ビュー"を表す一連のインタフェースを作成したいと考えていました。したがって、リクエストはViewTypeのBasicで提供されます。つまり、ユーザーの個人情報と住所が必要です。だから私は、私はこのような変換コール作ることができることを期待して、UserBasicと呼ばれるインタフェースを書いて、それを実装するためにユーザーを持って、そしてUserBasicMapperにUserBasicからのマッピングを追加し、UserBasicBeanからUserBasicMapperへ:

UserBasicBean restrictedUserReturn = (UserBasicBean) getDomainBeanMapper().mapDomainToBean((UserBasic)user); 

をが、これは動作しません。なぜなら、getClass()は、キャストされたインタフェースではなく、インスタンスクラスを常に返します。私はいつも私が使用したいクラスであるmapDomainToBeanコールに別のパラメータを追加することができますが、コードベースは非常に大規模で、その変更を行う場合はすべての呼び出しに触れる必要があります。

基本的に私は、インターフェイスタイプにインスタンスをキャストし、そのインターフェイスタイプを見つける方法を探していますか?これは可能ですか?

十字指 ...

+0

なぜオブジェクト全体が必要なのですか? –

+0

セキュリティ要件です。システムの特定のユーザは、オブジェクトの特定の部分だけを見ることができます。 – Margaret

答えて

3

ユーザーが実装するインターフェイスを作成するのではなく、限定バージョンを表すプロキシクラスを作成してみましょう。例えば、

class UserBasic { 

    private User user; 

    public UserBasic(User user) { 
     this.user = user; 
    } 

    public String getFirstName() { 
     return user.getFirstName(); 
    } 
    ... 
} 

は、その後、あなたは完全なインスタンスを取り戻すためにgetUser() { return user; }を追加することができます。

このようにして、他のすべてを同じに保ち、インターフェイス上のクラスのトレードオフを行うことができます。

+1

おっと、これはいいです!!!私には同じ機能があり、domainBeanMapperコードをまったく変更する必要はありません。 UserBasicはgetUser()メソッドを使用して、サブオブジェクトビューを提供するリクエストに対して、別の方向にマッピングできるようにすることもできます。はい、これは素晴らしいことです! – Margaret

+0

ha、優れています、私は自分のコメントを書いていたので、getUserを追加しました。本当にありがとうございました! – Margaret

+1

喜んで助けてください! @マーガレット – ChiefTwoPencils

0

私はわからないが、あなたはそれがあるオブジェクトの種類を確認するためにのinstanceofキーワードを使用することができます。

+1

は、残念ながらそれは本当に私が言っていると同じように仕事に行くのではありません \t (myObjectというINSTANCEOF UserBasic){ \t \tマッパー= findApplicableMapper( "UserBasic")であれば、 \t}それ以外の場合(myObjectというINSTANCEOF AnotherView){ \t \t ..... \t} いるだろう私のコードまで本当に汚いです。思考のおかげで。 – Margaret

+0

私が探しているのは、instanceOfの実装の背後にあるコードを利用して、myObjectがどのインスタンスであるかを調べる方法です。これは利用できないと愚かに思われる – Margaret

0

あなたは、paramenterタイプとは異なるいくつかのメソッドを書くように例を何かを作ることができます。

public class Test 
{ 

    public static void n(Number n) { 
     System.out.println("Number"); 
    } 

    public static void n(Integer n) { 
     System.out.println("Integer"); 
    } 

    public static void main(String[] args) 
    { 
     n(3); //will call the n(Integer n); 
     n((Number)3); //will call the n(Number n); 
    } 
} 

そうです、あなたが複数のメソッドにそれぞれ取って、適切なパラメータの型を作ることによってにキャストしているタイプかを調べることができますそれに応じて入力して処理します。

+0

残念ながら私はこのパスを使用できるとは思わない。私は、私のオブジェクトにさまざまなビューの複数のインターフェイスを実装させるつもりです。すべては、メンバー変数の関連ゲッターとセッターのオーバーラップセットです。例えば。ユーザーは、UserBasic、UserLight、UserLocationを実装します。 instanceofチェックを使用すると、Userオブジェクトがそれらをすべて実装するので、すべてのインスタンスに対してtrueを返します。私はちょうど私がそれをキャストしたどのタイプをチェックするのではなく。それは意味がありますか?私はちょうどキャストされている特定のインターフェイスを見つける必要があります。 – Margaret

0

インターフェイスはビューを表さず、動作を定義します。 私はあなたが「サブオブジェクトのについて何かを言うならあなたには、いくつかここに工場の種類(インスピレーションhttps://en.wikipedia.org/wiki/Factory_method_patternhttps://sourcemaking.com/design_patterns/abstract_factoryのためのこれらのリンクをckech)(またはビルダー) を必要とする推測 -

class BaseUserBean extends UserBean {} 
class AnotherUserBean extends UserBean {} 

プットUserBeanのクラスを拡張しよう共通の基底クラスと、あなたのサブユーザのそれぞれには本当に特定の何かにすべてのユーザーのためのもののは、子供のクラスに言わせて、その後、

UserBean u = getDomainBeanMapper().mapDomainToBean(user); 

...

//method mapToDomain should check your param and return the type you need 
//ViewType can be a part of user or a separate param 
UserBean mapDomainToBean(User user, ViewType vt) { 
    if (vt == ViewType.BASE) { 
     BaseUserBean obj = BaseUserBean(); 
     // mapping here (set fields you need) 
     return obj; 
    } 

    if (vt == ViewType.ANOTHER) { 
     AnotherUserBean obj = AnotherUserBean(); 
     // mapping here (set fields you need) 
     return obj; 
    } 
    ... 
} 
+0

これは確かに可能ですが、ありがとうございますが、mapDomainToBeanのシグネチャを変更すると数百のスポットに影響を及ぼし、回帰テストの時間はあまりにも慎重にすぎません。 – Margaret

関連する問題