Я разрабатываю настольное приложение на Java Swing с использованием шаблона проектирования MVC и реализую слои Service
и DAO
.Уровень DAO взаимодействует с базой данных, а уровень Service
связывается с Controller
.Вот реализация DAO:
public class ProductDAO implements DAO {
public void insert(Product p) throws SQLException {
//Logic for insertion goes here.. i.e. Getting/pooling connection object and executing PreparedStatement etc.
}
public List<Product> listAll() throws SQLException {
//Logic for retreive
}
.
.
.
}
И Service
Слой:
public class ProductService implements Service {
private DAO dao;
private Controller con;
public ProductService(Controller con) {
dao = new ProductDAO();
this.con = con;
}
public void insertProduct(Product p) throws SQLException {
dao.insertProduct(p);
con.onSuccess();
}
.
.
.
}
Но DAO может занять много времени (при получении всех продуктов и составлении списка), он долженисполняться в фоновом потоке.С Swing
лучший подход для запуска длинной задачи - использование потока SwingWorker
.(Я работал с SwingWorker
и его методами). Но тут я понял, что этот слой должен реализовывать SwingWorker
Мысли:
- Реализация SwingWorker на другом слое (скажем
Executer
): Этот слой Executer
будет находиться между Service
layer и DAO
layer.Он унаследует SwingWorker
и обеспечит реализацию doInBackground()
и другим методам.Объекты Service
и DAO
будут внедрены из слоя Service
.Слой Service
создаст новый экземпляр и вызовет метод execute()
слоя Executer
, а также определит режим работы, такой как insert
, update
или delete
.Этот слой Executer
вызовет соответствующий метод DAO
, например, если режим работы insert
, то он вызовет insertProduct(Product p)
метод DAO
.Вот реализация этой мысли:
Уровень исполнителя
public class ProductExecuter extends SwingWorker<Void, Void> {
private Service.Mode mode;
private Service service;
private DAO dao;
private Product product;
public ProductExecuter(Service s, DAO d, Product p, Service.Mode mode) {
this.service = s;
this.dao = d;
this.mode = mode;
this.product = p;
}
@Override
public Void doInBackground() {
if(mode.equals(Service.INSERT)) {
dao.insertProduct(product);
service.onSuccess();
} else if(mode.equals(Service.GET_ALL)) {
List<Product> list = dao.listAll();
service.setListData(list);
}
.
.
.
}
}
Уровень обслуживания
public class ProductService implements Service {
private SwingWorker<Void, Void> executer;
private Dao dao;
public ProductService(Controller con) {
this.con = con;
this.dao = new ProductDAO();
}
public void insertProduct(Product p) {
executer = new ProductExecuter(this, dao, p, Mode.INSERT);
executer.execute();
}
public void listAll() {
executer = new ProductExecuter(this, dao, null, Mode.GET_ALL);
executer.execute();
}
public void onSuccess() {
con.onSuccess(); //**This method will interact with VIEW and might change GUI state. So this should be on EDT**
}
public void setListData(List<Product> list) {
con.setListData(list); //**This method will interact with VIEW and might change GUI state. So this should be on EDT**
}
.
.
.
.
public enum Mode {
INSERT, GET_ALL, REMOVE, UPDATE, GET_BY_ID;
}
}
Так что мой вопрос заключается в том, как мне реализовать SwingWorker с Service
и DAO
.
- Должен ли я перейти к рассмотренной выше мысли?или SwingWorker должен быть реализован на уровне Service или что-то еще, чего я не знаю