Расширяет AbstractTableModel и динамически заполняет jTable

По сути, я работаю над архитектурой клиент-сервер, поэтому некоторые клиенты могут изменять объекты извне.

У меня есть банк:

public class Bank{
    private List<BankingOperation> operationList = new ArrayList<BankingOperation>();

    public void addOperation(BankingOperation op) {
        this.operationList.add(op);
//...
}

И мой сервер:

public class ServerBank extends JFrame {
    private Bank bank;
    private JTable table;
    private OperationTableModel model;

    public ServerBank() {
        this.bank = new Bank();
        this.model= new OperationTableModel(this.bank.getOperationList());
        table = new JTable(model);
        getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
        pack();
    }

    public static void main (String args[]) throws Exception {

        ServerBank frame=new ServerBank();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800,700);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);


    }
    class OperationTableModel extends AbstractTableModel {

    private static final long serialVersionUID = 1L;
    private List<BankingOperation> operationList;
    public String[] colNames = { "Date", "Login", "Customer","Account", "Operation", "Amount", "Final Balance" };
    public Class<?>[] colTypes = { String.class, String.class, String.class, String.class, String.class, Integer.class,
            Integer.class };


    public OperationTableModel(List<BankingOperation> operationList) {
        super();
        this.operationList = operationList;
    }//...
}

Клиенты могут добавить операцию в список операций банка, вызвав addOperation().

Возникает вопрос: как JTable может обнаружить это и обновить отображение?

Поскольку клиенты не используют методы TableModel для добавления операций. У них нет доступа к этому классу. Кроме того, я не знаю, является ли хорошей идеей предоставление всего списка операций банка в конструкторе TableModel...


person xenom    schedule 03.12.2012    source источник


Ответы (1)


Предоставляя клиентам доступ к внутреннему списку, используемому банком, вы позволяете им делать что-то за банком банка. Немного похоже на то, если бы реальный банк дал доступ к своей внутренней базе данных, вместо того, чтобы заставлять всех клиентов проходить через приложение онлайн-банка.

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

Например, метод addOperation() реализации интерфейса не только добавит операцию в список операций, но и вызовет событие табличной модели, чтобы таблица отобразила эту добавленную операцию.

Это можно сделать напрямую, если банк инкапсулирует табличную модель, или косвенно, запустив настраиваемое событие «добавление операции». Модель таблицы будет прослушивать эти события и запускать собственное событие модели таблицы для обновления таблицы.

person JB Nizet    schedule 03.12.2012
comment
По сути, клиентам предоставляется сеанс для выполнения своей операции только в том случае, если соединение было успешным. Но я обязан передать экземпляр банка конструктору сеанса, верно? Потому что фактически я не отправляю весь экземпляр банка клиентам, но даже для списка операций в сеансе мы должны выполнять операции над чем-то, поэтому у меня есть конструктор Session(Bank bank); Что касается проблемы с таблицей, насколько я понимаю, решение будет состоять в том, чтобы инкапсулировать саму модель таблицы и удалить мой ArrayList of Operation? (Потому что ArrayList уже был бы в табличной модели). - person xenom; 03.12.2012
comment
Да, вы действительно можете инкапсулировать модель таблицы в банк, а банк — в сеанс. Это делает все чрезвычайно тесно связанным и нереалистичным для реального приложения, но идея состоит в том, чтобы сделать это. Использование событий и прослушивателей событий сделало бы все это менее связанным. - person JB Nizet; 03.12.2012
comment
Что ж, если архитектура нереалистична, я бы предпочел прослушиватели событий и событий. Но я не очень понимаю, как это сделать. Потому что, если Session не знает Bank, как он может вызывать методы Bank? - person xenom; 03.12.2012
comment
Посмотрите, как работает JButton. Он ничего не знает о вашем приложении. Но когда вы щелкаете по нему, он вызывает метод вашего приложения, который вы реализовали сами. Это происходит потому, что ваше приложение добавляет прослушиватель к кнопке, и кнопка вызывает этот прослушиватель при нажатии. Сделайте то же самое с банком и сессией: банк добавляет в сессию листнер. Когда операция выполнена, сеанс запускает событие. Банк получает сообщение от сеанса и обновляет свою табличную модель. - person JB Nizet; 03.12.2012
comment
Проблема в том, что банк не является сервером. Фактически сервер создает экземпляр банка, а также создает экземпляр сеанса. Вот почему Банк не знает Session. Как вы думаете, предпочтительнее ли объединить Сервер с самим Банком? Если я поступаю таким образом, я более или менее понимаю, как работать с основными банковскими операциями и прослушивателем. Но что касается восстановления баланса или списка аккаунтов? Как вы справляетесь со слушателем? Сессия сообщит банку, что клиенту нужна его/ее информация, но как вы получите возвращаемое значение? - person xenom; 03.12.2012