I am trying to implement a simple observer pattern in java and I am running into an issue that I cannot seem to figure out. I have the following:
public interface Observable {
public void addView(Observer view);
public void removeView(Observer view);
public void notifyView();
public Object getUpdate(Observer view);
}
public class Data implements Observable {
//List to hold all of the views observing data changes.
private ArrayList<Observer> views = new ArrayList<Observer>();
private ArrayList<Integer> data = new ArrayList<Integer>();
...
#Override
public void notifyView() {
for (Observer view: views){
//issue here
view.update(data);
}
}
...
}
I am getting an error in my notifyView() method when I try to call the view.update() method. The error I get is:
The method update(Observable, Object) in the type Observer is not applicable for the arguments (ArrayList<Integer>)
I do not understand this because I have my Observer interface, and class set up as follows:
public interface Observer {
public void update(ArrayList<Integer> data);
}
public class View implements Observer{
#Override
public void update(ArrayList<Integer> data) {
// TODO Auto-generated method stub
}
}
I have tried reading other posts but nothing has helped me. Is there something I am overlooking that is causing this problem?
Your code is not using your Observer class, instead, is using the Java's Observer class
https://docs.oracle.com/javase/7/docs/api/java/util/Observer.html
You should rename your Observer interface name to another to see problem. For example MyObserver. You have conflict with JDK standard Observer interface ( please see your Data.java import section) and your Observer interface. Be more accurate with interface names.
Related
Question
I'm having trouble understanding the following UML-diagram of the Observer pattern from the "Elements of Reusable Object-Oriented Software". Could anyone explain me why my Java implementation is wrong and what I have to change to implement it correctly?
UML-Diagram
Attempted (but wrong) implementation
public interface Subject {
public static final List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer o);
public void detach(Observer o);
public void notifyObservers();
}
public interface Observer {
public void update();
}
public class ConcreteSubject implements Subject {
private String subjectState;
#Override
public void attach(Observer o) {
observers.add(o);
}
#Override
public void detach(Observer o) {
observers.remove(o);
}
#Override
public void notifyObservers() {
for (Observer o : observers) {
o.update();
}
}
public String getState() {
return subjectState;
}
public void setState() {
subjectState += "x";
}
}
public class ConcreteObserver implements Observer {
private ConcreteSubject subject;
public String observerState;
#Override
public void update() {
observerState = subject.getState();
}
}
One problem is that you have a static list of observers in Subject so all subjects share the same observers. However, the pattern requires that each individual subject has its own observers so put the list into ConcreteSubject and make it an instance field.
Another problem is that your ConcreteObserver has a field of type ConcreteSubject. It should, however, not know about the concrete implementation of Subject so the field should only have the type Subject.
Edit: Actually the UML diagram requires the concrete observer to know about the concrete subject in order to be able to call getState() so the above paragraph is not true in your case - this should not be a problem here.
However, in reality I would actually have another interface that extends Subject and hides the implementation of ConcreteSubject from the observer.
Edit 2:
As has been suggested you could also use an abstract class to handle the observers of a subject. That could be a class in between Subject and ConcreteSubject or even Subject itself but since Java doesn't support multiple inheritance I'd often use some other approach and make Subject just an interface.
The easiest implementation would then be to have ConcreteSubject maintain the list of observers but in a real world application you'd not want to have developers do that or rely on them implementing it correctly.
Instead you could use a central registry that maintains the list of observers for each subject and which the subject uses to inform its observers. Many dependency injection frameworks out there operate in a way like that, i.e. whenever a "subject" changes they will inform its observers about that event.
This seems like an elementary problem so I'm sure it's something small I've overlooked. Maybe I've just been looking at it too long.
I've been trying to create an onClick Listener in a view, and I have a public set method to set the listener. But when I try to call that method outside of the class I get an error saying it can't resolve the method.
I've tried creating other public methods or public member variables but I can't view any of them outside of the class for some reason.
Here is some relative snippets:
PaintView: (The class I can't get public members from)
public class PaintView extends View {
public interface OnPaintClickedListener
{
public void onPaintClicked(int color);
}
private OnPaintClickedListener _onPaintClickedListener;
public void setOnPaintClickedListener(OnPaintClickedListener listener)
{
_onPaintClickedListener = listener;
}
...
}
PaletteView: (The class that uses a PaintView)
public class PaletteView extends ViewGroup {
....
public void addColor(Context context, int color)
{
View newPaintView = new PaintView(context, color);
//setOnPaintClickedListener gives the message "Cannot resolve method setOn...blah blah'
newPaintView.setOnPaintClickedListener(new PaintView.OnPaintClickedListener()
{
#Override
public void onPaintClicked(int color)
{
}
});
this.addView(newPaintView);
}
}
It does ok with the interface code, but it just can find that setOnPaintClickedListener method.
Thanks in advance, I'm 97% sure I'm going to feel like an idiot as soon as somebody points out my mistake.
Change to:
PaintView newPaintView = new PaintView(context, color);
explanation...as the variable you were using was declared with type View, the compiler wasn't able to find the method that was defined in the subclass PaintView, so it complains.
Alternatively, you could leave the same declaration and when calling the specific method, you would have to do cast to the subclass like this:
((PaintView)newPaintView).setOnPaintClickedListener
I am implementing the Observer / Observable pattern using Java. However, I am encountering a problem in the Observer portion of my code.
Observable
public class Model extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<A>());
this.notifyObservers(new ArrayList<B>());
}
}
Observer
public class View implements Observer {
#Override
public void update(Observable observable, Object object) {
// TODO: If object is ArrayList<A>?
System.out.println("A");
// TODO: If object is ArrayList<B>?
System.out.println("B");
}
}
How would I fill in the TODO comments to check for the generic on the ArrayList? Is this even possible? (I would prefer to do it without implementing more classes, if possible.)
An Observable should send one and only one type of data.
public class ModelA extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<A>());
}
}
public class ModelB extends Observable {
public void notify() {
this.setChanged();
this.notifyObservers(new ArrayList<B>());
}
}
Your other alternative is to put ArrayList<A> and ArrayList<B> into a class. You can notify your observers with that class.
You could use instanceof to see what type is your object but you are misusing the pattern.
The idea is that the Observable has a well defined interface and all the Observer needs to know is to use the API to pass the notification.
Logic to know what exactly is the Observable should not be mixed in the code.
From your question sounds to me you have 2 Observable and they should keep their own listeners interested specifically in them for notification. Not one combined
While reading up on the Class Adapter pattern in Head First Design Patterns, I came across this sentence:
class adapter... because you need multiple inheritance to implement it, which is not possible in Java
Just to experiment, I tried the following:
interface MyNeededInterface{
public void operationOne(MyNeededInterface other);
public MyNeededInterface operationTwo();
}
public class ThirdPartyLibraryClass{
public void thirdPartyOp();
}
Suppose I create :
class ThirdPartyWrapper extends ThirdPartyLibraryClass implements MyNeededInterface{
#Override
public void operationOne(ThirdPartyWrapper other){
this.thirdPartyOp();
dosomeExtra();
}
#Override
public ThirdPartyWrapper operationTwo(){
int somevalue = doSomeThingElse();
return new ThirdPartyWrapper(somevalue);
}
}
In my code, I can use:
MyNeededInterface myclass = createThirdPartyWrapper();
myclass.operationOne(someobj);
...
Is this not the Class Adapter pattern?
The class adapter pattern is not possible in Java because you can't extend multiple classes. So you'll have to go with the adapter pattern which uses composition rather than inheritance.
An example of the adapter pattern through composition can be found below:
interface Duck
{
public void quack();
}
class BlackDuck implements Duck
{
public void quack() { }
}
class Turkey
{
public void gobble() { }
}
class TurkeyAdapter implements Duck
{
private Turkey t;
public TurkeyAdapter(Turkey t)
{
this.t = t;
}
public void quack()
{
// A turkey is not a duck but, act like one
t.gobble();
}
}
Now you can pass a Turkey to a method which is expecting a Duck through the TurkeyAdapter.
class DuckCatcher
{
public void catch(Duck duck) { }
}
By using the adapter pattern the DuckCatcher is now also able to catch Turkey(Adapter)s and Ducks.
Yes, you can create a class adapter with an interface as long as you're only wrapping a single adaptee. With multiple inheritance you could take two or more adaptees and wrap them into a single interface.
The full story in heads up is: class adapter pattern is impossible in Java just because Java does not provide multiple inheritance.
In their diagram, they show that the Adapter class subclasses both Target and Adaptee. Your example is (close to) the Object adapter pattern. The difference is that you implement the Target in your adapter class, rather then just subclassing the target (MyNeededInterface in your example)
GoF (Gang of Four) tells us about two major kinds of adapters:
A. Class adapters. They generally use multiple inheritance to adapt one interface to another. (But we must remember, in java, multiple inheritance through classes is not supported (for a good reason :) ). We need interfaces to implement the concept of multiple inheritance.)
B. Object adapters. They depend on the object compositions.
To illustrate the concepts, I'll present a simple example:
(source: book Java Design Patterns)
interface IIntegerValue
{
public int getInteger();
}
class IntegerValue implements IIntegerValue
{
#Override
public int getInteger()
{
return 5;
}
}
// Adapter using interface
class ClassAdapter extends IntegerValue
{
//Incrementing by 2
public int getInteger()
{
return 2 + super.getInteger();
}
}
// Adapter using composition
class ObjectAdapter implements IIntegerValue
{
private IIntegerValue myInt;
public ObjectAdapter(IIntegerValue myInt)
{
this.myInt=myInt;
}
//Incrementing by 2
public int getInteger()
{
return 2+this.myInt.getInteger();
}
}
class ClassAndObjectAdapter
{
public static void main(String args[])
{
System.out.println("Class and Object Adapter Demo");
ClassAdapter ca1=new ClassAdapter();
System.out.println("Class Adapter is returning :"+ca1.getInteger());
ClassAdapter ca2=new ClassAdapter();
ObjectAdapter oa=new ObjectAdapter(new IntegerValue());
System.out.println("Object Adapter is returning :"+oa.getInteger());
}
}
Console output:
Class and Object Adapter Demo
Class Adapter is returning :7
Object Adapter is returning :7
Class Adapters are kind of possible in Java by using single inheritance.
As an example from Design pattern for dummies, suppose we have to adapt AWT checkboxes to be used alongside with Swing checkboxes, we can write a class adapter for this.
The UI code in Swing to determine if a check box is checked is done with the isSelected method. But, AWT check boxes dont support isSelected(), they use getState() instead.
So we can write an adapter to wrap an SWT check box and adapt the getState() to isSelected()
public class CheckboxAdapter extends Checkbox
{
public CheckboxAdapter(String n)
{
super(n);
}
public boolean isSelected()
{
return getState();
}
}
Now we can handle AWT adapted check boxes as we would standard Swing check boxes when it comes to the isSelected method.
public void itemStateChanged(ItemEvent e)
{
String outString = new String("Selected: ");
for(int loopIndex = 0; loopIndex
<= checks.length - 1; loopIndex++){
if(checks[loopIndex].isSelected()) {
outString += " checkbox " + loopIndex;
}
}
text.setText(outString);
}
EDIT: True class adapter are not possible in Java, if they were we could inherit from multiple classes, which we want to mimic in an adapter class.
Also see http://www.journaldev.com/1487/adapter-design-pattern-in-java-example-tutorial for two examples in Java using Class Adapter and Object adapter, to achieve same result.
Given the following Class and Service layer signatures:
public class PersonActionRequest {
PersonVO person
// ... other fields
}
public class MyServiceLayerClass {
public void requestAction(PersonActionRequest request)
{
PersonVO abstractPerson = request.getPerson();
// call appropriate executeAction method based on subclass of PersonVO
}
private void executeAction(PersonVO person) {}
private void executeAction(EmployeeVO employee) {}
private void executeAction(ManagerVO manager) {}
private void executeAction(UnicornWranglerVO unicornWrangler) {}
}
As discussed here, java will select the best method based on type info at compile time. (Ie., it will always select executeAction(PersonVO person) ).
What's the most appropriate way to select the correct method?
The internet tells me that using instanceof gets me slapped. However, I don't see the appropraite way to select the method without explictly casting abstractPerson to one of the other concrete types.
EDIT: To Clarify - The VO passed in is a simple ValueObject exposed for web clients to instantiate and pass in. By convention it doesn't have methods on it, it's simply a data structure with fields.
For this reason, calling personVO.executeAction() is not an option.
Thanks
Marty
If executeAction was a method in a base class or interface that was common to PersonVO, EmployeeVO, ManagerVO and UnicornWranglerVO, you could just call abstractPerson.executeAction() instead of having multiple overridden methods.
Your principle obstacle to polymorphism here seems to be a 'dumb-struct' data object + 'manager class' service non-pattern. The "more polymorphic' approach would be for execute() to be a method that the various person implementations override.
Assuming that can't change, the way you do multiple dispatch in Java is with visitor-looking callbacks.
public interface PersonVisitor {
void executeAction(EmployeeVO employee);
void executeAction(ManagerVO manager);
void executeAction(UnicornWranglerVO unicornWrangler);
}
public abstract class PersonVO {
public abstract void accept(PersonVisitor visitor);
}
public class EmployeeVO extends PersonVO {
#Override
public void accept(PersonVisitor visitor) {
visitor.executeAction(this);
}
}
public class MyServiceLayerClass implements PersonVisitor {
public void requestAction(PersonActionRequest request)
{
PersonVO abstractPerson = request.getPerson();
abstractPerson.accept(this);
}
public void executeAction(EmployeeVO employee) {}
public void executeAction(ManagerVO manager) {}
public void executeAction(UnicornWranglerVO unicornWrangler) {}
}
You could change the way you are approaching the design and use a Visitor, passing the executor into the Person and have the person type determine which to call.
The Visitor pattern is often used to overcome Java lacking double-dispatch.
I would explicitly cast the abstractPerson. Not only does it ensure the JVM gets the right method, it makes it a hell of a lot easier to read and ensure you know what's going on.