Single-dispatch, dispatch double and two design patterns

What is the single and double dispatch dispatch

Assignment (dispatch) is in accordance with the object of the actual type of process for binding a corresponding method thereof.

For example, two class and its subclasses X X1, X2, they have achieved instance method m () - usually subclass X1, X2, should be added before the method @Override, so there are three m ().

For message expression am (b, c), according to the actual type of an object corresponding to binding constructs, known as single dispatch. Of course, this "object" special, each message expression am (b, c) there is only one message recipient, the "object" refers to the message recipient , i.e., am (b, c) of the A . Therefore, only the actual recipient of the message type binding method provide actual type of body, i.e., a single dispatch (singledispatch) , is object-oriented dynamic binding!

Suppose that for message expression am (b, c), if the actual type can be a, b and c of the body for binding the corresponding method is called three dispatched. For simplicity, double research assignment (double dispatch) is enough.

A so-called double dispatch , it is desirable A.foo (b) the actual type can be ① a method of binding override its body, and can bind ② i.e. its overloaded method foo (Y) of the actual type b, foo (Y1), an appropriate method thereof foo (Y2) of. [Related concepts, refer to the "design mode .5.11 visitor pattern" p223]

Unfortunately, Java does not support dual assignment. For the method foo (X), foo (X1 ) and foo (X2) these overloaded, Java at compile time, it is foo (b) b according to the declared type of static binding of foo (X) This method body, the actual type b is not to judge X1 or X2. Java can be used in the runtime type identification (Run-Time TypeIdentification, RTTI) technique, using keywords instanceof determine the actual type. Although the parent class declared type Y, the program re-declared type of the actual temp, and the shape parameter downwardly. RTTI Although the code is simple, but elegant enough to use branching statements. Further, ① programmer also noted that the specific type judgment front; ②RTTI operation will take more time and space.

"Java programming ideas" in, there is a saying

In addition to static methods in Java and final method (private method belongs to the final method), all other methods are late binding, which is the binding runtime, we need not determine whether it should be a late-bound - it will happen automatically.

I mentioned here late binding, but also to select a specific method for declaring type parameters.

Bis-dependent design pattern dispatched

Since when Java support am (b), by a specific type of the corresponding binding way, that if in some way am (b) implementation, completed b.m1 () call, that does not achieve " double dispatch "yet? Overview GOF23, there are two design patterns perfectly support this kind, which are command mode and Visitor Pattern

Command mode dual assignment

FIG command mode UML

Let me talk a digression, I believe we can be seen from UML diagram some problems, why Client Invoker both need to know what they need to know Receiver, Client Invoker role accepts commands and executes commands while the real perpetrators of the command is Receiver, with "Zen design pattern" in the example, Invoker is the project manager, Receiver is a work of art or code farmers and so on. In accordance with the Law of Demeter, then Client should not know Receiver. We discuss this issue on the back. Look at the code below:

Abstract receiver

public abstract class Receiver {
    abstract void doSth();
}
复制代码

ConcreteReceiver1

public class ConcreteCommand1 extends Command {
    private Receiver receiver;

    public ConcreteCommand1(Receiver receiver) {
        this.receiver = receiver;
    }

    @Override
    void execute(Receiver receiver) {
        System.out.println("我是command1, 入参是Receiver");
        receiver.doSth();
    }

    @Override
    void execute(ConcreteReceiver1 receiver) {
        System.out.println("我是command1, 入参是ConcreteReceiver1");
        receiver.doSth();
    }

    @Override
    void execute(ConcreteReceiver2 receiver) {
        System.out.println("我是command1, 入参是ConcreteReceiver2");
        receiver.doSth();
    }
}

复制代码

Abstract Command

public abstract class Command {
    private Receiver receiver;

    public Command(Receiver receiver) {
        this.receiver = receiver;
    }
    abstract void execute(Receiver receiver);

    abstract void execute(ConcreteReceiver1 receiver);

    abstract void execute(ConcreteReceiver2 receiver);

    public Receiver getReceiver() {
        return receiver;
    }
}

复制代码

ConcreteCommand1

public class ConcreteCommand1 extends Command {
    public ConcreteCommand1(Receiver receiver) {
        super(receiver);
    }

    @Override
    public Receiver getReceiver() {
        return super.getReceiver();
    }

    @Override
    void execute(Receiver receiver) {
        System.out.println("我是command1, 入参是Receiver");
        receiver.doSth();
    }

    @Override
    void execute(ConcreteReceiver1 receiver) {
        System.out.println("我是command1, 入参是ConcreteReceiver1");
        receiver.doSth();
    }

    @Override
    void execute(ConcreteReceiver2 receiver) {
        System.out.println("我是command1, 入参是ConcreteReceiver2");
        receiver.doSth();
    }
}
复制代码

ConcreteCommand2

public class ConcreteCommand2 extends Command {
    public ConcreteCommand2(Receiver receiver) {
        super(receiver);
    }

    @Override
    void execute(Receiver receiver) {
        System.out.println("我是command2, 入参是Receiver");
        receiver.doSth();
    }

    @Override
    void execute(ConcreteReceiver1 receiver) {
        System.out.println("我是command2, 入参是ConcreteReceiver1");
        receiver.doSth();
    }

    @Override
    void execute(ConcreteReceiver2 receiver) {
        System.out.println("我是command2, 入参是ConcreteReceiver2");
        receiver.doSth();
    }

    @Override
    public Receiver getReceiver() {
        return super.getReceiver();
    }
}

复制代码

Invoker

public class Invoker {
    private Command command;

    public void setCommand(Command command) {
        this.command = command;
    }

    public void act() {
        this.command.execute(command.getReceiver());
    }
}

复制代码

client

public class Client {
    public static void main(String[] args) {
        Invoker invoker = new Invoker();

        Receiver receiver1 = new ConcreteReceiver1();
        Receiver receiver2 = new ConcreteReceiver2();

        Command command1 = new ConcreteCommand1(receiver1);
        Command command2 = new ConcreteCommand2(receiver2);

        invoker.setCommand(command1);
        invoker.act();
    }
}
复制代码

Results of the

我是command1, 入参是Receiver
receiver1 处理命令1
复制代码

analysis

To Minato am (b) This format, which makes ugly, forgive me. Client in, Receiver and Command are declared by the interface, when the implementation of invoker.setCommand(command1); invoker.act();the time, go to the program

i.e. a this.command, Java can be found in a specific category; and b is the declared type Receiver, Java is not to identify, it can be seen ConcreteCommand1.execute(Receiver); , therefore Java binding the first method of ConcreteCommand1

We see a printout is 我是command1, 入参是Receiver

In this method, it has become a Receiver a.m(b)in a, but also as a method of Java binding according to the actual type, so went ConcreteReceiver1 in hard-to shame holding am (b), here again Lorry wordily He wrote three overloaded methods. Then b is ConcreteCommand1, so finding overloaded methods

See printout receiver1 处理命令1

Visitor Pattern

Understand the Visitor pattern friends to see this certainly say that this is where the command mode tm ah, obviously dressed in command mode skin of visitor patterns Well! Indeed, to find ways to explain the double assignment, the command mode has been out sick, may wish to take a look at the visitor pattern. For example, "Zen design patterns," the

Film actors play the role of an actor can play multiple roles, we first define a film in two roles: kung fu hero and idiot supporting role

public interface Role { 
//演员要扮演的角色 
} 
public class KungFuRole implements Role { 
//武功天下第一的角色 
} 
public class IdiotRole implements Role { 
//一个弱智角色 
}
复制代码

With roles, we then define an abstract class actor

public abstract class AbsActor {
    //演员都能够演一个角色 
    public void act(Role role){
        System.out.println("演员可以扮演任何角色");
    }
    //可以演功夫戏 
    public void act(KungFuRole role){
        System.out.println("演员都可以演功夫角色");
    }
}
复制代码

Very simple, Java is used here overload, we look at the young actors and older actors, using the overwritten way to refine the function abstract class

public class YoungActor extends AbsActor {
    //年轻演员最喜欢演功夫戏 
    public void act(KungFuRole role){
        System.out.println("最喜欢演功夫角色");
    }
}
public class OldActor extends AbsActor {
    //不演功夫角色 
    public void act(KungFuRole role){
        System.out.println("年龄大了,不能演功夫角色");
    }
}
复制代码

Override and overload already achieved, we wrote a scenario,

public class Client {
    public static void main(String[] args) {
//定义一个演员 
        AbsActor actor = new OldActor();
//定义一个角色 
        Role role = new KungFuRole();
//开始演戏 
        actor.act(role);
        actor.act(new KungFuRole());
    }
}
复制代码

Get output

演员可以扮演任何角色
年龄大了,不能演功夫角色 
复制代码

Use section describes the methods mentioned, can very easily analyze the realization of the principle of double assignment.

Deep principle

We can find, achieved through design patterns double assignment, is actually a "pseudo-dual assignment" deep principle at least, need to read more, and so I read the "in-depth understanding of the Java virtual machine" after, will come back to this section Fill.

Reference Documents

www.iteye.com/topic/11307... www.voidcn.com/article/pd... "Zen Design Patterns" "Java programming ideas"

Guess you like

Origin juejin.im/post/5d79fabb6fb9a06b1777e2fd