2011-07-21 7 views
4
  • からクラスやメソッドを非表示にするには、「デフォルト」のJavaアクセスを使用することをお勧めします:

我々はファクトリメソッドを使用している場合は、我々が作成を返却する必要があります実装されたインタフェースのタイプとしての実装これは、クラスの場合は、クライアント

public class Factory { 

    public Product getProduct() { 
    return new ProductA(); 
    } 
} 

public interface Product { 
} 

class ProductA implements Product { 
} 

に我々が持っている製品{A、B、C ...など}の具体的な実装に戻った製品をキャストするクライアントの機能を回避するには、次の

  1. パッケージのクライアントと工場のコードは別々です(com.example.clientととしましょう)。 210)
  2. デフォルト( "パッケージ")アクセス方法の場合、()クライアントには見えない、工場から見える

package com.example.client; 
    ... 
    public class Client { 
     public static void main(String[] args) { 
     Product i = new Factory().getProduct(); 
     ProductA a = (ProductA) i; // the type of ProductA isn't visible. 
     } 
    } 
  • コンクリートimplemantations宣言:

たとえば、非表示の方法で同じ工場を使用する必要があります。

public class Factory { 

    public Product getProduct() { 
    return new ProductA(); 
    } 

    Product[] getCreatedProducts() { 
    ... 
    } 
} 

私はここで二つの問題を参照してください。

  • 悪いパッケージ構造:隠されたクラスやメソッドは、呼び出し元のコードで1つのパッケージにする必要があります。
  • 悪いコード:あまり直感的でわかりにくい。 Javaファイルを別のパッケージに置き換えることで簡単に中断することができます。
+0

「保護された」と同じだと思っていましたが、わかりません。私は常にアクセスキーワードを定義します。 –

+0

@Martijn 'protected'はパッケージとサブクラスからアクセス可能です。デフォルト(キーワードなし)はパッケージではアクセスできますが、サブクラスではアクセスできません。 – toto2

+0

@Aghasted私はあなたが正しいことをしていると思います。しかし、私はあなたの "二つの問題"を理解していません。なぜ私はあなたがなぜこれをやっているのかよく分かりません。クライアントからさまざまな 'Product'タイプを隠すのはなぜですか? – toto2

答えて

2

"デフォルト"アクセスでは、悪質なプログラマがあなたのパッケージ内でクラスを宣言することができるため、何も保証されません。また、あなたのパッケージ構造にかかわらず、Javaでは、ほとんどの場合、 "インスタンス"チェックを行い、次に "インスタンス"タイプにダウンキャストすることができます。したがって、ダウンキャストを防ぐことを目標にしている場合は、privateというキーワードを使用する必要があります。たとえば、Productインターフェイスの具体的な実装をprivate static、またはFactoryの匿名の内部クラスとして宣言できます。実際、Blochの「優れたAPIを設計する方法」の記事では、「すべてのアクセシビリティを最小限に抑える」という点を強調しています。

私はあなたがここでは少し編集的であると思います。誰かが倒産した場合、それはあなたにとって大きな問題になりますか?あなたが書いたコードは誤用される可能性があります。十分に文書化されたファクトリを含めると、APIを適切に使用する方法に関する明確な情報が提供されています。また、引数を取る実際のファクトリメソッドを構築し、メソッド名が明確な場合は、この玩具Factoryの例では引数をとらないのに対し、作成されているものの一般的に関連する部分をブロードキャストしていることがわかりますとにかく

2

私はなぜファクトリとクラスを別々のパッケージに入れたいのか分かりません。

私は通常、パブリックインターフェイス、パブリックファクトリクラス、およびパッケージで保護された実装を同じパッケージに作成します。したがって、クライアントはファクトリのみを使用してインスタンスを作成できます。具体的なクラスは他のパッケージからは表示されないため、キャストダウンできません。

+0

問題は「デフォルトのアクセス権が十分に利用可能か」ということでした。私はそうではないと思うし、常にアクセスキーワードを定義しなければならない。クライアントがメソッドをキャストして隠すのを防ぐより良い方法があるかどうかを知りたいだけです。 – trupanka

+0

@Aghastedパッケージで保護されたアクセスに問題があるのはなぜですか?これは実際には「デフォルト」ではなく、パッケージ保護されたアクセスに必要なキーワードがないことだけです。また、あなたの唯一の他の選択肢は、Factoryの内部クラスをプライベートにすることです。 – Bringer128

1

ここでは、クライアントが実装クラスを知っているファクトリを知っています。それらがすべて同じプロセスにある場合、クライアントと実装クラスの両方が同じプロセスにロードされます。つまり、クライアントはリフレクションによって実装クラスの基本メソッドにアクセスできます。これは、クライアントランタイムを完全に制御していない、つまりリフレクションを防ぐための対策を講じていないことを前提としています。しかし、そうした場合、おそらくクライアントが実装クラスにキャストできないことを心配する必要はありません。

これを信頼できないクライアントプロセスに対する潜在的なセキュリティメカニズムと見なすと、私は信用できません。あなたがクライアントを支配しているなら、誤ったプログラマーが意図しない混乱を起こさないようにするには、おそらく十分です。

2

2つのパッケージの利点はありません。私はこの代替を提案する:二つのパッケージを使用して

package com.example.client ; 
    public interface Product 
    { 
     /* stuff */ 
    } 

    package com.example.client ; 
    public interface ProductFactory 
    { 
     Product make (X1 x1 , X2 x2 , /* parameters */ , Xn xn) ; 
    } 

    package com.example.manager; 
    interface ManagedProduct extends com.example.client.Product 
    { 
     /* management methods */ 
    } 

    package com.example.manager ; 
    public final class DefaultProductFactory implements com.example.client.ProductFactory 
    { 
     public static final DefaultProductFactory instance = new DefaultProductFactory () ; 

     private DefaultProductFactory () 
     { 
       super () ; 
     } 

     public ManagedProduct make (final X1 x1 , final X2 x2 , /* parameters */ , final Xn xn) 
     { 
       return new ManagedProduct () 
       { 
        /* implementation logic here */ 
       } ; 
     } 

     /* 
       possibly other methods 
       The Product implementation class is invisible. 
      */ 
    } 
  1. は不必要com.example.manager.DefaultProductFactoryクラスに実装製品のクラスを公開します。私は自分のアプローチがBringer128's private inner class Factoryよりも優れていると主張します。私のアプローチでは、実装のProductクラスは、実装のFactoryクラスに存在する可能性のある他のメソッドでも見えません。
  2. パラメータをfinalにすると、メソッドの引数から直接、実装のProductクラスで使用できます((1)X1 x1、X2 x2、...、Xn xnメンバーを作成する必要はありません) this.x1 = x1、this.x2 = x2、...、this.xn = xn(コンストラクタ内)、(3)ProductImpl(x1、x2、...、xn)でコンストラクタを呼び出します。 。小さいが、それはあなたのキーストロークを保存し
  3. 私は強くphilwbに同意する。これは、セキュリティとみなすべきではない
  4. これはcom.example.managerのクラスは、他のパッケージ内のクラスよりも、同じオブジェクトに複数のメソッドを持つことができます。。 - Is this a good practice to use the "default" Java access to hide classes and methods from clientでリクエストされたとおりです。
関連する問題