A read-only object, Point
, to be exported out of a Facade:
public interface Point {
int getX();
int getY();
}
public interface Facade {
Point getPoint();
}
Usage is then ala
int x = myFacade.getPoint().getX();
Note that users of Facade can never mutate the point. It’s state is encapsulated.
A Strategy delegate behind the Facade needs to translate the Point (move delta in x,y direction). Provide access via a role interface, more specifically a private interface that provides a mutator method which allows translation only:
public interface TranslatablePoint {
void translation(int dx, int dy);
}
public interface PointStrategy() {
void doSomethingToPoint(TranslatablePoint p);
}
Then, we can create an implementation class for a point like
public class StandardPoint implements Point, TranslatablePoint {
[all three methods implemented here] }
public class MyFacade implements Facade {
StandardPoint point;Point getPoint() { return point; }
}
Now, an implementation like
public class Strategy1 implements PointStrategy {
void doSomethingToPoint(TranslatablePoint p) {
translation(+3, +7);
p.
} }
can be called from with the Facade like
strategy.doSomethingToPoint(point);
as the declared ‘point’ implements the TranslatablePoint.
However, an implementation of PointStrategy
cannot access (x,y) of the point, as these accessor methods are not part of the TranslatablePoint
interface.
This can be remedied by simply adding the relevant accessor methods:
public interface TranslatablePoint {
int getX();
int getY();
void translation(int dx, int dy);
}
Note that StandardPoint
implements two interface, each declaring that it must implement, say, int getX()
. But as it does so, this is no problem.
Delegates that are provided an instance of TranslatablePoint
can thus both access (x,y) and translate the point.
Benefit: You Program to an Interface - you can change the internal implementing class to something else than StandardPoint
without changing the strategies. You can specifically define which fields of the object to get access to. Liability: Duplication of method declarations in multiple places.
Often, if the original interface is a read-only interface, you can provide the access just by extending the interface:
public interface TranslatablePoint extends Point {
void translation(int dx, int dy);
}
In our case, the result is the same as in the above solution.
In case you basically just have the read-only interface and an internal mutable interface you can beneficially Program to an Interface in the Facade as well, ala
public class MyFacade implements Facade {
TranslatablePoint point;Point getPoint() { return point; }
}
Now, the actual implementing class can be substited or dependency injected in the Facade without any reliance on the concrete class.
Benefit: You Program to an Interface - you can change the internal implementing class to something else than StandardPoint
without changing the strategies. Less typing, access to all accessor methods.
Liability: Less control of what gets accessed.
A point can also be rotated a certain angle around origo. Of course you can also make a special role for that:
public interface RotablePoint {
void rotateOrigo(int degrees);
}
public class StandardPoint
implements Point, TranslatablePoint, RotablePoint {
[all four methods implemented here] }
etc.
Note this is the Interface Segregation Principle: Being specific about what operations a given delegate can do on the point, by declaring the method of the given fine-grained role interface.