пытается изменить значения с помощью firepropertychange, propertychangesupport - PullRequest
0 голосов
/ 10 января 2019

Я пишу Java-программу, используя propertychangesupport, changechange и fireproperty, теперь она работает, но не совсем, когда я изменяю значение и печатаю его, но когда я пытался выполнить цикл while для прослушивающего класса spesipic чтобы изменить его, просто выйдите из цикла, когда я поставлю его в состояние while,

публичный класс Main {

public static void main(String[] args) {
        CLI cli = new CLI(System.in,System.out);
        Server server = new Server(34567);
        cli.addPropertyChangeListener(server);
        new Thread(cli).start();
}

}

CLI открытого класса реализует Runnable {

private Scanner scanner;
private String userInput;
private PropertyChangeSupport pcs;
private Boolean serverIsRunning;

public CLI(InputStream in, OutputStream out){
    this.scanner = new Scanner(in);
    pcs = new PropertyChangeSupport(this);
    serverIsRunning = false;
}


@Override
public void run() {

    while (true) {
        System.out.println("pls enter your command:");
        userInput = scanner.nextLine().trim().toUpperCase();
        switch (userInput) {
            case "START":
                if (!serverIsRunning)   {
                    pcs.firePropertyChange(userInput, null, "START");
                    new Thread(new Server(34567)).start();
                    serverIsRunning = true;
                } else {
                    System.out.println("server is already running");
                }
                break;
            case "SHUTDOWN":
                if (serverIsRunning) {
                    pcs.firePropertyChange(userInput, null, "SHUTDOWN");
                    serverIsRunning = false;
                } else {
                    System.out.println("server is not running");
                }
                break;
        }
    }
}

public void addPropertyChangeListener(PropertyChangeListener pcl){
    this.pcs.addPropertyChangeListener(pcl);
}

public void removePropertyChangeListener(PropertyChangeListener pcl){
    this.pcs.removePropertyChangeListener(pcl);
}

}

открытый класс Server реализует Runnable, PropertyChangeListener {

private int port;
private ServerSocket server;
private String userInput = "";
private Boolean serverIsRunning;

public Server(int port) {
    this.port = port;
    serverIsRunning = true;
}

public void propertyChange(PropertyChangeEvent evt) {
        userInput = evt.getNewValue().toString();
        switch (userInput) {
            case "START":
                System.out.println("Starting server...");
                serverIsRunning = true;
                break;
            case "SHUTDOWN":
                serverIsRunning = false;
                break;
        }
    }


@Override
public void run() {
    try {
        server = new ServerSocket(port);
    } catch (IOException e) { }

    while (serverIsRunning) {
        try {
            new Thread(new Client(server.accept())).start();
        } catch (IOException e) { }
    }

    try {
        server.close();
        System.out.println("shutdown");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

1 Ответ

0 голосов
/ 10 января 2019

Опять же, основная цель использования шаблона проектирования слушателя состоит в том, чтобы избежать необходимости использовать цикл while для постоянного опроса об изменении состояния и вместо этого заставить совместную поддержку слушателя и слушателя уведомлять вас, когда состояние объекта меняется.

Другие вопросы:

  • Бин должен содержать прослушиваемое или "связанное" поле
  • Сам бин должен вызывать метод fireXxx в месте изменения состояния, а не любой из ваших других классов.
  • Слушатель не должен иметь или нуждаться в петле while (true). Все, что он должен делать, это слушать и реагировать на изменения состояния в Бобе, не больше и не меньше.

Например, скажите, что ваш боб выглядел так:

public class Bean2 {
    // constant for the property change name
    public static final String STATE = "state";
    private PropertyChangeSupport pcs;

    // this is the "bound" field
    private String state = "";

    public Bean2() {
        pcs = new PropertyChangeSupport(this);
    }

    public String getState() {
        return state;
    }

    // notify listeners within the setter
    public void setState(String state) {
        String oldValue = this.state;
        String newValue = state;
        this.state = state;
        pcs.firePropertyChange(STATE, oldValue, newValue);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(propertyName, listener);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }

    // method to remove... 

}

Тогда ваш слушатель может быть простым:

public class Listener2 implements PropertyChangeListener {
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println("From listener: state change -- new state: " + evt.getNewValue());
        // this code will obviously need to do more...
    }
}

и используется так:

public static void main(String[] args) {
    Bean2 bean = new Bean2();
    Listener2 listener = new Listener2();
    bean.addPropertyChangeListener(Bean2.STATE, listener);

    Scanner scanner = new Scanner(System.in);
    String text = "";
    while (!text.equalsIgnoreCase(EXIT)) {
        System.out.print("Enter text or \"EXIT\" to quit: ");
        text = scanner.nextLine();
        if (!text.equalsIgnoreCase(EXIT)) {
            bean.setState(text);
        }
    }
    scanner.close();
}

Видите, нет цикла while, нет вызова fireXxx из компонента


Что касается ваших правок, я все еще не на 100% уверен в том, что вся ваша программа настроена, но, возможно, что-то в этом роде:

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class MyServer2 {
    private static final String EXIT = "exit";
    public static final int PORT = 4444;
    private ServerSocket server;

    public MyServer2() throws IOException {
        server = new ServerSocket(PORT);
    }

    public void beanChanged(String text) {
        // *** not sure what you want to do with this text 
        // *** other than to check that it != EXIT
        if (!text.equalsIgnoreCase(EXIT)) {
            try {
                new Thread(new Client(server.accept()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            // System.exit(0); // ????
        }
    }

    public static void main(String[] args) {
        MyServer2 server = null;
        try {
            server = new MyServer2();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Bean2 bean = new Bean2();
        Listener2 listener = new Listener2(server);
        bean.addPropertyChangeListener(Bean2.STATE, listener);

        Scanner scanner = new Scanner(System.in);
        String text = "";
        while (!text.equalsIgnoreCase(EXIT)) {
            System.out.print("Enter text or \"EXIT\" to quit: ");
            text = scanner.nextLine();
            if (!text.equalsIgnoreCase(EXIT)) {
                bean.setState(text);
            }
        }
        scanner.close();
    }

}

public class Bean2 {
    // constant for the property change name
    public static final String STATE = "state";
    private PropertyChangeSupport pcs;

    // this is the "bound" field
    private String state = "";

    public Bean2() {
        pcs = new PropertyChangeSupport(this);
    }

    public String getState() {
        return state;
    }

    // notify listeners within the setter
    public void setState(String state) {
        String oldValue = this.state;
        String newValue = state;
        this.state = state;
        pcs.firePropertyChange(STATE, oldValue, newValue);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(propertyName, listener);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }

    // method to remove...

}

public class Listener2 implements PropertyChangeListener {
    private MyServer2 myServer2;

    public Listener2(MyServer2 myServer2) {
        this.myServer2 = myServer2;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        // notify server by calling its public method with new value
        myServer2.beanChanged((String) evt.getNewValue());
    }
}

public class Client implements Runnable {
    private Socket socket;

    public Client(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        // TODO finish coding

    }

}

Но это все еще чувствует себя неловко. Обратите внимание, что я обычно помещаю свой код в accept() нового клиента в своем собственном потоке, так как он блокирует код, что-то вроде:

new Thread(() -> {
    while (true) {
        try {
            new Thread(new Client(server.accept()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();
...