2016-07-11 18 views
0

私はプロジェクトで働いており、最も内側のクラスへのアクセスを許可したくありません。これは、私が使用しているクラス構造です。JAVAでのカプセル化のレベル

// data types are not important unless mentioned 
class One 
{ 
    protected propertyOne; 
    protected String id; 
} 

class Two 
{ 
    protected ArrayList<One> arrayOne; 
    protected String id; 
} 

class Three 
{ 
    protected ArrayList<Two> arrayTwo; 
    protected otherProperty; 
} 

ここで、メインクラスはThreeをインスタンス化し、メンバメソッドを通してTwoとOneを使用する必要があります。 get関数でArrayListのいずれかを返すと、すべてのデータをどこからでも簡単に変更できます。だからArrayList<Two>の代わりに、私はArrayList<Two.id>を返しており、別の方法が特にTwo.idと呼ばれています。これはArrayListを隠しておくようにしますが、ArrayList<Two.id>ArrayList<One.id>のために多くのコードと余分なオブジェクトを生成します。

C++では、constメソッドをconstの戻り値タイプに変更し、ArrayListに変更がないようにしました。

ArrayListを隠すためにJavaにスマートな方法はありますか?

+1

たとえば、次のようなゲッターメソッドを提供できます。呼び出し元が 'arrayTwo'を変更するのを防ぐために' Collections.unmodifiableList(arrayTwo) ' –

+2

私は 'protected'ではなく' private'も全てとしています。 'protected'は、同じパッケージ内の他のクラスやサブクラスへのアクセスを許可します。 –

+1

['コレクション。 unmodifiableList(リスト) '?](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiableList-java.util.List-) – Turing85

答えて

0

私たちは、hibernateベースのAPIで同様の問題があります。我々は、ビジネスロジックを一箇所に保ち、APIレベルでいくつかのアクセス制御を実施するために、サービスの使用を強制することで、「機密」の変更を不可能にしたいと考えました。

これをプロキシと派生したReadonlyインターフェイスで解決しました。

したがって、プロパティがTwoの場合、getXメソッドはReadonlyTwoインターフェイスで宣言されています。 Twoのリストを返すたびに、リストはReadonlyTwoであると宣言します。プログラマーは、APIを学ぶことでこれをハックすることができ、オブジェクトが実際にTwoであり、型キャストが可能なときに表示されます。これを避けるには、実際のTwoオブジェクトの周りにプロキシをラップし、ReadonlyTwoインターフェイスを実装する必要があります。

リストを不変リストとして返すと、APIは外部レベルの変更からオブジェクトレベルまで非常に安全です。

// data types are not important unless mentioned 
class One implements ReadonlyOne 
{ 
    protected propertyOne; 
    protected String id; 
} 

class Two implements ReadonlyTwo 
{ 
    protected ArrayList<? extends ReadonlyOne> arrayOne; 
    protected String id; 
} 

class Three implements ReadonlyThree 
{ 
    protected ArrayList<? extends ReadonlyTwo> arrayTwo; 
    protected otherProperty; 
} 

インタフェースは、この(あなたが任意のgetter/setterメソッドを追加していなかったので、私はここでそれらを構成している)のようになります。

interface ReadonlyThree { 
    List<? extends ReadonlyTwo>getArrayTwo(); 
} 

アプリケーションオブジェクトTwoの変更を処理するためのビジネスメソッドを必要とし、 Oneオブジェクト:

interface ThreeService { 
    ReadonlyTwo addTwo(p1, p2, p3) throws BusinessException; 
    void removeTwo(ReadonlyTwo twoRO) throws BusinessException; 
    List<? extends ReadonlyTwo>findTwoByPredicate(Predicate p) throws BusinessException; 
} 
+0

メソッド "getArrayTwo()"はワイルドカードを返します。 List getArrayTwo();が返されます。十分であろう。 – Teto

+0

@Teto:合意しましたが、これはまさにコンセプトです。 – thst

+0

申し訳ありません。私は質問として私のコメントを語ることを意味する。 List を返すのに十分でしょうか?私は配列の内容を保護するためのあなたのソリューションに同意します。私は同じような戦略を自分で使いました。それは概念の証明に過ぎません。 – Teto