I have following code:
Container
is an object that holds set of Part
s. Some of parts are able to tell to container that they changed (ObservablePart
notifies Container
via someObservableMarketChanged
method), and some just update their state (NonObservablePart
). In case that ObservablePart
changes, I need to do recalculation, and update all parts again (but this change is only applicable to NonObservablePart
s, ObservablePart
s have their values remain the same). The output of this program is:
Changing NONobservable id 4 from 1 -> 235
Changing NONobservable id 3 from 1 -> 235
Changing observable id 1 from 1 -> 235
Changing NONobservable id 4 from 235 -> 236
Changing NONobservable id 3 from 235 -> 236
Changing NONobservable id 4 from 236 -> 236
Changing NONobservable id 3 from 236 -> 236
Changing observable id 2 from 1 -> 235
Changing NONobservable id 4 from 236 -> 470
Changing NONobservable id 3 from 236 -> 470
Changing NONobservable id 4 from 470 -> 470
Changing NONobservable id 3 from 470 -> 470
and as you can see there is too much unneeded calls. What I wanted to have is this:
Changing observable id 1 from 1 -> 235
Changing observable id 2 from 1 -> 235
Changing NONobservable id 4 from 1 -> 470
Changing NONobservable id 3 from 1 -> 470
It is possible to have this case implemented as easy as:
void doit(){
allParts.stream()
.filter(x -> x instanceof ObservablePart)
.forEach(x -> x.updateMe(235));
Map<Integer, Part> changed = onlyNonObservableMarketsChange();
for(Part m : allParts){
m.updateMe(changed.get(m.getId()).getVal());
}
}
So, basically, instead of ObservablePart
notifying Container
that it's state changed, I have to put all the logic inside Container
, and Container
is not more dumb container that just forwards responsibility to Part
objects. Now, it has to know which parts are observable and which are not, and that it first needs to update all observable parts, and only then it can do some calculations and update non-observable parts.
Is this use of observer pattern an overkill in this case? Should I just put this logic inside Container
, since code and reasoning is much more straightforward?
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class Differ {
public static void main(String[] args) {
Container m = new Container();
m.allParts = Set.of(
new ObservablePart(1,m),
new ObservablePart(2,m),
new NonObservablePart(3),
new NonObservablePart(4)
);
m.doit();
}
}
class Container {
public Set<Part> allParts = new HashSet<>();
void doit(){
for(Part m : allParts){
m.updateMe(235);
}
}
//this would not be in Container, just needed for example
int getSumOfObservableMarkets(){
return allParts.stream()
.filter(x -> x instanceof ObservablePart)
.mapToInt(x -> ((ObservablePart) x).val)
.sum();
}
//this would not be in container, but something else would calc. changes
Map<Integer, Part> onlyNonObservableMarketsChange(){
int obsSum = getSumOfObservableMarkets();
return allParts.stream()
.collect(Collectors.toMap(k -> k.getId(), m -> {
if(m.getId()==1 || m.getId()==2){
return m;
}
m.updateMe(obsSum);
return m;
}));
}
void someObservableMarketChanged(){
Map<Integer, Part> changed = onlyNonObservableMarketsChange();
for(Part m : allParts){
m.updateMe(changed.get(m.getId()).getVal());
}
}
}
interface Part {
int getId();
int getVal();
void updateMe(int val);
}
class ObservablePart implements Part {
Container container;
ObservablePart(int id, Container m){this.id=id;
container =m;}
public int id;
int val = 1;
public int getId() {return id;}
public int getVal() {return val;}
public void updateMe(int val) {
if(this.val != val) {
System.out.printf("Changing observable id %s from %s -> %s%n", id, this.val, val);
this.val = val;
container.someObservableMarketChanged();
}
}
}
class NonObservablePart implements Part {
public int id;
int val = 1;
public NonObservablePart(int id) {this.id = id;}
public int getId() {return id;}
public int getVal() {return val;}
public void updateMe(int val) {
System.out.printf("Changing NONobservable id %s from %s -> %s%n", id, this.val, val);
this.val = val;
}
}
Aucun commentaire:
Enregistrer un commentaire