我在java中实现了简单的反演员:
public class CounterJavaActor extends UntypedActor {
int count = 0;
@Override
public void onReceive(Object message) throws Exception {
if (message.equals("incr")) {
count += 1;
} else if (message.equals("get")) {
sender().tell(count, self());
}
}
}
在课程“scala中的功能反应式编程”课程中,我看到了反函数的功能性实现:
/**
* Advantages:
* state change is explicit
* state is scoped to current behaviour
*/
class CounterScala extends Actor{
def counter(n: Int) : Receive = {
case "incr" => context.become(counter(n+1))
case "get" => sender ! n
}
def receive = counter(0)
}
UPD :
我的问题,在java中我不能像scala counter(n+1)
那样进行求助函数调用。这意味着什么:
public class CounterJava8Actor extends AbstractActor {
//counter(0) in scala
private PartialFunction<Object, BoxedUnit> counter;
private int n = 0;
public CounterJava8Actor() {
counter =
ReceiveBuilder.
matchEquals("get", s -> {
sender().tell(n, self());
}).
matchEquals("inc", s -> {
//become(counter(n+1) in scala
context().become(counter);
}).build();
receive(counter);
}
}
可以用java实现它的功能风格吗?
答案 0 :(得分:4)
根据你可以使用的文档成为/不成为java 8
http://doc.akka.io/docs/akka/snapshot/java/lambda-actors.html#become-unbecome
这是从那里复制的示例代码
public class HotSwapActor extends AbstractActor {
private PartialFunction<Object, BoxedUnit> angry;
private PartialFunction<Object, BoxedUnit> happy;
public HotSwapActor() {
angry =
ReceiveBuilder.
matchEquals("foo", s -> {
sender().tell("I am already angry?", self());
}).
matchEquals("bar", s -> {
context().become(happy);
}).build();
happy = ReceiveBuilder.
matchEquals("bar", s -> {
sender().tell("I am already happy :-)", self());
}).
matchEquals("foo", s -> {
context().become(angry);
}).build();
receive(ReceiveBuilder.
matchEquals("foo", s -> {
context().become(angry);
}).
matchEquals("bar", s -> {
context().become(happy);
}).build()
);
}
}
或者您可以使用UntypedActor,如此处的文档中所述
http://doc.akka.io/docs/akka/snapshot/java/untyped-actors.html
public class Manager extends UntypedActor {
public static final String SHUTDOWN = "shutdown";
ActorRef worker = getContext().watch(getContext().actorOf(
Props.create(Cruncher.class), "worker"));
public void onReceive(Object message) {
if (message.equals("job")) {
worker.tell("crunch", getSelf());
} else if (message.equals(SHUTDOWN)) {
worker.tell(PoisonPill.getInstance(), getSelf());
getContext().become(shuttingDown);
}
}
Procedure<Object> shuttingDown = new Procedure<Object>() {
@Override
public void apply(Object message) {
if (message.equals("job")) {
getSender().tell("service unavailable, shutting down", getSelf());
} else if (message instanceof Terminated) {
getContext().stop(getSelf());
}
}
};
}
要了解如何将参数添加到Procedure
,您可以看到以下答案:
Akka/Java getContext().become with parameter?
这是java 8的实际解决方案
private PartialFunction<Object, BoxedUnit> counter(final int n) {
return ReceiveBuilder.
matchEquals("get", s -> {
sender().tell(n, self());
}).
matchEquals("inc", s -> {
context().become(counter(n + 1));
}).build();
}
public CounterJava8Actor() {
receive(counter(0));
}