如何从Akka 2.5 ReceiveBuilder的每个案例中提取公共代码 [英] How do I extract common code from every case of an Akka 2.5 ReceiveBuilder
问题描述
我正在将现有代码库迁移到Akka 2.5.1和Java 8(来自Akka 2.4.8 / Java 7),我的代码如下:
public void onReceive(Object message)throws Exception {
/ * Start type specific processing * /
if(message instanceof Foo){
processFoo();
} else if(message instanceof Bar){
processBar();
} else if(message instanceof Bash){
processBash();
} else if(message instanceof Otherthing){
processOtherThing();
}
/ *结束类型特定处理* /
/ *开始常用处理* /
doSomethingForAllMessages();
/ *结束常用处理* /
}
在Akka 2.5.1使用 ReceiveBuilder
这看起来像:
public接收createReceive(){
返回receiveBuilder()
.match(Foo.class,this :: processFoo)
.match(Bar.class,this :: processBar)
.match(Bash.class,this :: processBash)
.match(OtherThing.class,this :: processOtherThing)
.build();
}
...除了这不执行常见处理 doSomethingForAllMessages()
。是否有惯用的Java 8 / Akka 2.5.1方法进行一次这种常见处理,而不是将其添加到每个 match()
子句中?
更新
我正在寻找类似的东西:
< pre class =lang-java prettyprint-override>
public Receive createReceive(){
return receiveBuilder()
.match(Foo.class,this :: processFoo)
.match(Bar.class,this :: processBar)
.match(Bash.class,this :: processBash)
.match(OtherThing.class,this :: processOtherThing)
.andThen(this :: doSomethingForAllMessages)
.build();
}
你实际返回的是一个收到
而不是 ReceiveBuilder
。如果你想处理所有可以编写 scala.PartialFunction
的消息,因为接收
是最终。例如:
接收createReceive(){
return thenAccept(
receiveBuilder()
.match(Foo.class,this :: processFoo)
.match(Bar.class,this :: processBar)
.match(Bash.class,this :: processBash)
.match (OtherThing.class,this :: processOtherThing)
.build(),
this :: doSomethingForAllMessages
);
}
< T>接收thenAccept(接收原点,FI.UnitApply< T>动作){
返回新接收(thenAccept(origin.onMessage(),action));
}
< A,B>部分功能< A,B> thenAccept(PartialFunction< A,B> fn,
FI.UnitApply< A> action){
return Function.unlift(thenAccept(fn.lift(),action));
}
< A,B>功能1< A,选项< B>> thenAccept(Function1< A,Option< B>> fn,
FI.UnitApply< A> action){
return it - > {
选项< B> value = fn.apply(it);
action.apply(it);
返回值;
};
}
IF 您不想操作 scala
api可以满足您的需求。出于某种原因,例如: Function1
在先前版本中不是 scala
中的@FunctionalInterface。你可以编写 ReceiveBuilder
。例如:
public接收createReceive(){
return thenAccept(
receiveBuilder()
.match(Foo.class,this :: processFoo)
.match(Bar.class,this :: processBar)
.match(Bash.class,this :: processBash)
。 match(OtherThing.class,this :: processOtherThing),
this :: doSomethingForAllMessages
).build();
}
ReceiveBuilder thenAccept(ReceiveBuilder origin,FI.UnitApply< Object> action){
return ReceiveBuilder.create()。matchAny(allOf(
origin.build) ()。onMessage():: apply,
action
));
}
FI.UnitApply< Object> allOf(FI.UnitApply< Object> ... actions){
return it - > {
for(FI.UnitApply< Object> action:actions){
action.apply(it);
}
};
}
OR 您可以通过组合保持语义一致性 ReceiveBuilder
s。
public接收createReceive(){
return两个(
receiveBuilder()
.match(Foo.class,this :: processFoo)
.match(Bar.class,this :: processBar)
.match(Bash。 class,this :: processBash)
.match(OtherThing.class,this :: processOtherThing),
receiveBuilder()。matchAny(this :: doSomethingForAllMessages)
).build();
}
两个ReceiveBuilder(左边是ReceiveBuilder,右边是ReceiveBuilder){
返回ReceiveBuilder.create()。matchAny(它 - > Stream.of(左,右)
.map(ReceiveBuilder :: build)
.map(Receive :: onMessage)
.forEach(action-> action.apply(it)));
}
或 thenAccept
行为看起来像属于 ReceiveBuilder
,但您需要付出更多努力来实现它,并在使用时破坏封装 继承。
public接收createReceive(){
返回AcceptableReceiveBuilder.create()
.match(Foo.class,this :: processFoo)
.match(Bar.class,this :: processBar)
.match(Bash.class,this :: processBash)
.match(OtherThing.class,this :: processOtherThing)
.thenAccept(this :: doSomethingForAllMessages)
.build();
}
类AcceptableReceiveBuilder扩展了ReceiveBuilder {
private List< FI.UnitApply< Object>> afterActions = new ArrayList<>();
public static AcceptableReceiveBuilder create(){
return new AcceptableReceiveBuilder();
}
@Override
public
< P> AcceptableReceiveBuilder匹配(Class< P> type,FI.UnitApply< P> action){
return this.matchUnchecked(type,action);
}
@Override
public
AcceptableReceiveBuilder matchUnchecked(Class<?> type,
FI.UnitApply<?> action){
return(AcceptableReceiveBuilder)super.matchUnchecked(输入
,compose(action));
}
@Override
public
< P> AcceptableReceiveBuilder匹配(类< P>类型,
FI.TypedPredicate< P>条件,
FI.UnitApply< P>操作){
返回this.matchUnchecked(类型,条件,操作);
}
@Override
public
< P> AcceptableReceiveBuilder matchUnchecked(Class<?> type,
FI.TypedPredicate<?> condition,
FI.UnitApply< P> action){
return(AcceptableReceiveBuilder)super.matchUnchecked(type,条件
,compose(action));
}
@Override
public
< P> AcceptableReceiveBuilder matchEquals(P值,FI.UnitApply< P> action){
return(AcceptableReceiveBuilder)super.matchEquals(value
,compose(action));
}
@Override
public
< P> AcceptableReceiveBuilder matchEquals(P值,
FI.TypedPredicate< P>条件,
FI.UnitApply< P>动作){
return(AcceptableReceiveBuilder)super.matchEquals(value,condition
撰写(动作));
}
@Override
public
AcceptableReceiveBuilder matchAny(FI.UnitApply< Object> action){
return(AcceptableReceiveBuilder)super.matchAny(compose(行动));
}
private
< P> FI.UnitApply< P>撰写(FI.UnitApply< P>动作){
返回值 - > {
action.apply(value);
for(FI.UnitApply< Object> it:afterActions){
it.apply(value);
}
};
}
public
AcceptableReceiveBuilder thenAccept(FI.UnitApply< Object> action){
afterActions.add(action);
返回此;
}
}
I am migrating an existing codebase to Akka 2.5.1 and Java 8 (from Akka 2.4.8 / Java 7) and I have code like:
public void onReceive(Object message) throws Exception {
/* Start type specific processing */
if (message instanceof Foo) {
processFoo();
} else if (message instanceof Bar) {
processBar();
} else if (message instanceof Bash) {
processBash();
} else if (message instanceof Otherthing) {
processOtherThing();
}
/* End type specific processing */
/* Start common processing */
doSomethingForAllMessages();
/* End common processing */
}
In Akka 2.5.1 using ReceiveBuilder
this looks like:
public Receive createReceive() {
return receiveBuilder()
.match(Foo.class, this::processFoo)
.match(Bar.class, this::processBar)
.match(Bash.class, this::processBash)
.match(OtherThing.class, this::processOtherThing)
.build();
}
... except that this doesn't do the common processing doSomethingForAllMessages()
. Is there an idiomatic Java 8 / Akka 2.5.1 way of doing this common processing once instead of adding it to each match()
clause?
Update
I am looking for something like:
public Receive createReceive() {
return receiveBuilder()
.match(Foo.class, this::processFoo)
.match(Bar.class, this::processBar)
.match(Bash.class, this::processBash)
.match(OtherThing.class, this::processOtherThing)
.andThen(this::doSomethingForAllMessages)
.build();
}
what you actually return is a Receive
not a ReceiveBuilder
. if you want to process all of the messages you can composing scala.PartialFunction
since Receive
is final. for example:
Receive createReceive() {
return thenAccept(
receiveBuilder()
.match(Foo.class, this::processFoo)
.match(Bar.class, this::processBar)
.match(Bash.class, this::processBash)
.match(OtherThing.class, this::processOtherThing)
.build(),
this::doSomethingForAllMessages
);
}
<T> Receive thenAccept(Receive origin, FI.UnitApply<T> action) {
return new Receive(thenAccept(origin.onMessage(), action));
}
<A, B> PartialFunction<A, B> thenAccept(PartialFunction<A, B> fn,
FI.UnitApply<A> action) {
return Function.unlift(thenAccept(fn.lift(), action));
}
<A, B> Function1<A, Option<B>> thenAccept(Function1<A, Option<B>> fn,
FI.UnitApply<A> action) {
return it -> {
Option<B> value = fn.apply(it);
action.apply(it);
return value;
};
}
IF you don't want to operate scala
api to achieve your needs. for some reason, e.g: Function1
is not a @FunctionalInterface in scala
in prior version. you can composing ReceiveBuilder
s. for example:
public Receive createReceive() {
return thenAccept(
receiveBuilder()
.match(Foo.class, this::processFoo)
.match(Bar.class, this::processBar)
.match(Bash.class, this::processBash)
.match(OtherThing.class, this::processOtherThing),
this::doSomethingForAllMessages
).build();
}
ReceiveBuilder thenAccept(ReceiveBuilder origin, FI.UnitApply<Object> action) {
return ReceiveBuilder.create().matchAny(allOf(
origin.build().onMessage()::apply,
action
));
}
FI.UnitApply<Object> allOf(FI.UnitApply<Object>... actions) {
return it -> {
for (FI.UnitApply<Object> action : actions) {
action.apply(it);
}
};
}
OR you can keeping semantics consistency by combine ReceiveBuilder
s.
public Receive createReceive() {
return both(
receiveBuilder()
.match(Foo.class, this::processFoo)
.match(Bar.class, this::processBar)
.match(Bash.class, this::processBash)
.match(OtherThing.class, this::processOtherThing),
receiveBuilder().matchAny(this::doSomethingForAllMessages)
).build();
}
ReceiveBuilder both(ReceiveBuilder left, ReceiveBuilder right) {
return ReceiveBuilder.create().matchAny(it -> Stream.of(left,right)
.map(ReceiveBuilder::build)
.map(Receive::onMessage)
.forEach(action->action.apply(it)));
}
OR the thenAccept
behavior looks like belongs to ReceiveBuilder
, but you need take more efforts to achieve it, and it break encapsulation when using inheritance.
public Receive createReceive() {
return AcceptableReceiveBuilder.create()
.match(Foo.class, this::processFoo)
.match(Bar.class, this::processBar)
.match(Bash.class, this::processBash)
.match(OtherThing.class, this::processOtherThing)
.thenAccept(this::doSomethingForAllMessages)
.build();
}
class AcceptableReceiveBuilder extends ReceiveBuilder {
private List<FI.UnitApply<Object>> afterActions = new ArrayList<>();
public static AcceptableReceiveBuilder create() {
return new AcceptableReceiveBuilder();
}
@Override
public
<P> AcceptableReceiveBuilder match(Class<P> type, FI.UnitApply<P> action) {
return this.matchUnchecked(type, action);
}
@Override
public
AcceptableReceiveBuilder matchUnchecked(Class<?> type,
FI.UnitApply<?> action) {
return (AcceptableReceiveBuilder) super.matchUnchecked(type
, compose(action));
}
@Override
public
<P> AcceptableReceiveBuilder match(Class<P> type,
FI.TypedPredicate<P> condition,
FI.UnitApply<P> action) {
return this.matchUnchecked(type, condition, action);
}
@Override
public
<P> AcceptableReceiveBuilder matchUnchecked(Class<?> type,
FI.TypedPredicate<?> condition,
FI.UnitApply<P> action) {
return (AcceptableReceiveBuilder) super.matchUnchecked(type, condition
, compose(action));
}
@Override
public
<P> AcceptableReceiveBuilder matchEquals(P value, FI.UnitApply<P> action) {
return (AcceptableReceiveBuilder) super.matchEquals(value
, compose(action));
}
@Override
public
<P> AcceptableReceiveBuilder matchEquals(P value,
FI.TypedPredicate<P> condition,
FI.UnitApply<P> action) {
return (AcceptableReceiveBuilder) super.matchEquals(value, condition
, compose(action));
}
@Override
public
AcceptableReceiveBuilder matchAny(FI.UnitApply<Object> action) {
return (AcceptableReceiveBuilder) super.matchAny(compose(action));
}
private
<P> FI.UnitApply<P> compose(FI.UnitApply<P> action) {
return value -> {
action.apply(value);
for (FI.UnitApply<Object> it : afterActions) {
it.apply(value);
}
};
}
public
AcceptableReceiveBuilder thenAccept(FI.UnitApply<Object> action) {
afterActions.add(action);
return this;
}
}
这篇关于如何从Akka 2.5 ReceiveBuilder的每个案例中提取公共代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!