I am working with a project and don't want to give access to the innermost classes. This is the class structure I am using,
// 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;
}
Now, main class will instantiate Three and should use Two and One through member methods. If I return any of ArrayList
through get function, all the data can be easily changed from anywhere. So instead of ArrayList<Two>
, I am returning ArrayList<Two.id>
and then another method is called with particular Two.id
. This takes care of keeping ArrayList
s hidden but generates lots of code and extra objects because of ArrayList<Two.id>
and ArrayList<One.id>
.
In C++, I would have made a const
method with const
return type to ensure no changes in ArrayList
.
Is there any smart way in Java to keep ArrayList
s hidden?
答案 0 :(得分:0)
We have a similar issue with a hibernate based API. We wanted to make "accidential" change impossible, enforcing the use of services to keep the business logic in one place and enforcing some access control on the API level.
We did resolve this with proxies and a derived Readonly interface.
So if you have a property in Two
, the getX
method is declared in a ReadonlyTwo
interface. Whenever you return a list of Two
, you declare the list to be of ReadonlyTwo
. The programmer can hack around this by learning the API and he will see, when the object is really Two
and can be typecasted. If you want to avoid that, you would have to wrap a proxy around the real Two
object, implementing the ReadonlyTwo
interface.
If you now return the lists as immutable lists, your API is pretty safe from external modification, even down to the object level.
// 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;
}
Interfaces look like this (you did not add any getter/setter methods, so I make them up here):
interface ReadonlyThree {
List<? extends ReadonlyTwo>getArrayTwo();
}
Your application objects requires business methods to handle the modification of Two
and One
objects:
interface ThreeService {
ReadonlyTwo addTwo(p1, p2, p3) throws BusinessException;
void removeTwo(ReadonlyTwo twoRO) throws BusinessException;
List<? extends ReadonlyTwo>findTwoByPredicate(Predicate p) throws BusinessException;
}