我有以下代码: Container
是一个包含一组 Part
s。一些零件能够告诉容器它们已经改变了( ObservablePart
通知 Container
通过 someObservableMarketChanged
方法),有些只是更新它们的状态( NonObservablePart
). 万一 ObservablePart
更改后,我需要重新计算,并再次更新所有部分(但此更改仅适用于 NonObservablePart
是的, ObservablePart
它们的值保持不变)。
在这个例子中,我有两个可观察的部分和两个不可观察的部分。每当任何可观察部分发生变化时,我就必须把所有可观察部分的值作为输入,并为不可观察部分计算新的值。如果我使用观察者模式,一旦我更新了第一个可观察对象,它就会通知我——我能不能等到所有可观察对象都更新了(但可能其他可观察对象根本不会改变它的值),然后再重新计算?
如果观测值是异步的——在我看来这会更容易,我只会中断当前的计算,并用新值触发它。
该程序的输出为:
Changing observable id 1 from 1 -> 235
Changing NONobservable id 4 from 1 -> 236
Changing NONobservable id 3 from 1 -> 236
Changing observable id 2 from 1 -> 235
Changing NONobservable id 4 from 236 -> 470
Changing NONobservable id 3 from 236 -> 470
//notice that order of updates even metter
//so here I get this overwritten from first sync observable
Changing NONobservable id 4 from 470 -> 235
Changing NONobservable id 3 from 470 -> 235
正如你所看到的,有太多不必要的电话。我想要的是:
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
可以很容易地实施此案例:
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());
}
}
所以,基本上 ObservablePart
通知 Container
它的状态改变了,我必须把所有的逻辑放进去 Container
,和 Container
是不是更愚蠢的容器,只是把责任 Part
物体。现在,它必须知道哪些部分是可观察的,哪些是不可观察的,并且它首先需要更新所有可观察的部分,只有这样它才能进行一些计算并更新不可观察的部分。
在这种情况下,使用观察者模式是一种过度杀伤力吗?我应该把这个逻辑放进去吗 Container
,因为代码和推理要简单得多?
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;
}
}
暂无答案!
目前还没有任何答案,快来回答吧!