Я работаю над проектом, в котором у нас есть несколько классов предметной области для моделирования бизнес-данных. Эти классы являются простыми POJO, и мне нужно отобразить несколько таблиц, используя их. Например, рассмотрим этот класс:
public class Customer {
private Long id;
private Date entryDate;
private String name;
private String address;
private String phoneNumber;
public Customer(Long id, Date entryDate, String name, String address, String phoneNumber) {
this.id = id;
this.entryDate = entryDate;
this.nombre = name;
this.domicilio = address;
this.telefono = phoneNumber;
}
// Getters and setters here
}
Затем я создал свою собственную табличную модель, основанную на AbstractTableModel. для работы непосредственно с классом Customer
:
public class CustomerTableModel extends AbstractTableModel {
private final List<String> columnNames;
private final List<Customer> customers;
public CustomerTableModel() {
String[] header = new String[] {
"Entry date",
"Name",
"Address",
"Phone number"
};
this.columnNames = Arrays.asList(header);
this.customers = new ArrayList<>();
}
@Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0: return Date.class;
case 1: return String.class;
case 2: return String.class;
case 3: return String.class;
default: throw new ArrayIndexOutOfBoundsException(columnIndex);
}
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
Customer customer = getCustomer(rowIndex);
switch (columnIndex) {
case 0: return customer.getEntryDate();
case 1: return customer.getName();
case 2: return customer.getAddress();
case 3: return customer.getPhoneNumber();
default: throw new ArrayIndexOutOfBoundsException(columnIndex);
}
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return true;
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex < 0 || columnIndex >= getColumnCount()) {
throw new ArrayIndexOutOfBoundsException(columnIndex);
} else {
Customer customer = getCustomer(rowIndex);
switch (columnIndex) {
case 0: customer.setEntryDate((Date)aValue); break;
case 1: customer.setName((String)aValue); break;
case 2: customer.setAddress((String)aValue); break;
case 3: customer.setPhoneNumber((String)aValue); break;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
}
@Override
public int getRowCount() {
return this.customers.size();
}
@Override
public int getColumnCount() {
return this.columnNames.size();
}
@Override
public String getColumnName(int columnIndex) {
return this.columnNames.get(columnIndex);
}
public void setColumnNames(List<String> columnNames) {
if (columnNames != null) {
this.columnNames.clear();
this.columnNames.addAll(columnNames);
fireTableStructureChanged();
}
}
public List<String> getColumnNames() {
return Collections.unmodifiableList(this.columnNames);
}
public void addCustomer(Customer customer) {
int rowIndex = this.customers.size();
this.customers.add(customer);
fireTableRowsInserted(rowIndex, rowIndex);
}
public void addCustomers(List<Customer> customerList) {
if (!customerList.isEmpty()) {
int firstRow = this.customers.size();
this.customers.addAll(customerList);
int lastRow = this.customers.size() - 1;
fireTableRowsInserted(firstRow, lastRow);
}
}
public void insertCustomer(Customer customer, int rowIndex) {
this.customers.add(rowIndex, customer);
fireTableRowsInserted(rowIndex, rowIndex);
}
public void deleteCustomer(int rowIndex) {
if (this.customers.remove(this.customers.get(rowIndex))) {
fireTableRowsDeleted(rowIndex, rowIndex);
}
}
public Customer getCustomer(int rowIndex) {
return this.customers.get(rowIndex);
}
public List<Customer> getCustomers() {
return Collections.unmodifiableList(this.customers);
}
public void clearTableModelData() {
if (!this.customers.isEmpty()) {
int lastRow = customers.size() - 1;
this.customers.clear();
fireTableRowsDeleted(0, lastRow);
}
}
}
До сих пор все просто отлично. Однако у этого подхода есть как минимум две проблемы:
Поскольку мне нужно реализовать одну табличную модель для каждого класса, я буду генерировать много повторяющегося кода, чтобы, по сути, сделать три вещи: определить соответствующий заголовок таблицы, добавить/удалить объекты в/из базовой структуры (списка), переопределить оба
setValueAt()
иgetValueAt()
методов для работы с пользовательскими объектами.Допустим, у меня есть тот же список клиентов, но я должен представить его в двух разных таблицах с разными заголовками или данными. Мне пришлось бы создать подкласс моей модели таблицы и переопределить все, что нужно, чтобы выполнить это требование. Это совсем не кажется элегантным.
Вопрос. Есть ли способ избавиться от шаблонного кода, сделав мою табличную модель гибкой и пригодной для повторного использования?