DAO có nên độc thân hay không?


14

Tôi đang phát triển API RESTful và tôi nghĩ việc sử dụng DAO cho tài nguyên của mình là thuận tiện vì mặc dù tôi dự định chỉ sử dụng bộ nhớ để lưu trữ chúng, tôi không muốn đóng cửa với bất kỳ ai đang sử dụng thư viện của mình nếu họ quyết định sử dụng triển khai cơ sở dữ liệu cho DAO.

Câu hỏi của tôi là liệu DAO có nên là một người độc thân hay không. Nếu không, dịch vụ sẽ có phiên bản DAO và nó sẽ trông giống như thế này:

@Path("eventscheduler")
public class EventSchedulerService {
    private IEventSchedulerDao dao = new EventSchedulerDao();

    // in case a different implementation is to be used
    public void setEventSchedulerDao(IEventSchedulerDao dao) {
        this.dao = dao;
    }

    @Path("{uniqueName}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Tournament getTournament(@PathParam("name") String uniqueName) {
        return dao.get(uniqueName);
    }

    @Path("create")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Tournament createTournament(Tournament tournament) {
        return dao.create(tournament);
    }
}

Mặc dù nếu DAO là một người độc thân, nhưng tôi đoán sẽ không có nhiều sự khác biệt, chỉ trong dòng đầu tiên:

private IEventSchedulerDao dao = EventSchedulerDao.getInstance();

Tôi vẫn sẽ phải sử dụng một IEventSchedulerDaoví dụ, nhưng tôi đoán tất cả các singleton đều hoạt động như thế này phải không? Vì một số lý do, tôi luôn luôn tương quan các singletons với các phương thức tĩnh, vì vậy thay vì có một cá thể singleton hiển thị cho người dùng vớigetInstance() , điều này sẽ bị ẩn và anh ấy / cô ấy sẽ chỉ sử dụng EventSchedulerDao.get(name), v.v ... theo kiểu tĩnh. Đây là một điều hay đây chỉ là tôi?

Vì vậy, tôi nên hay không nên có DAO đơn?

Và như một câu hỏi phụ, liệu cách tiếp cận của tôi có mở ra cho người dùng thực hiện DAO của họ không?


Bạn có thể sử dụng một đơn vị IoC thay vì một đơn vị có bộ truy cập tĩnh.
CodeInChaos

Câu trả lời:


10

Tôi sẽ không sử dụng một singleton. Đó là một mô hình chống được công nhận và làm cho việc kiểm tra khó khăn. Tôi sẽ có nhiều thay bơm trong một thực hiện cụ thể, và có tham khảo dịch vụ của bạn một giao diện DAO (cho phép bạn bơm triển khai khác nhau trong)


1
Những gì bạn đề nghị trong câu cuối cùng của bạn chính xác là những gì tôi đang làm phải không?
dabadaba

1
Bạn đang tham khảo qua một giao diện (có), nhưng bạn không tiêm DAO (để rõ ràng ....)
Brian Agnew

Ý anh là gì? Tôi có một setter cho nó, phải không?
dabadaba

@dabadaba Đường dây private IEventSchedulerDao dao = new EventSchedulerDao();là nơi bạn đã đi sai. Việc thực hiện IEventSchedulerDaonên được đưa vào thông qua hàm tạo và không bao giờ thay đổi (nghĩa là loại bỏ setEventSchedulerDaoquá).
David Arno

Được rồi tôi hiểu rồi. Tôi chỉ làm điều đó để cung cấp một DAO mặc định và thay đổi nó sẽ là "tùy chọn". Nhưng theo gợi ý của bạn có nghĩa là có một hàm tạo cho dịch vụ khác với mặc định và tôi không biết làm thế nào nó hoạt động với Jersey vì nó sử dụng hàm tạo mặc định. Bạn có biết làm thế nào để làm điều đó không?
dabadaba

4

A D ata A ccess O bject chỉ nên thực sự tồn tại một lần trong ứng dụng của bạn. Logic vẫn như cũ, điều duy nhất khác biệt là các giá trị đến và đi trong các phương thức mà DAO cung cấp.

Với ý nghĩ đó, rõ ràng điều đầu tiên thường xảy ra là triển khai DAO như một đơn vị mạnh , đó là khi bạn có một staticphương thức trên lớp nhà máy, đại loại như getInstance, lười tải một thể hiện của DAO nếu nó không có giá trị và trả lại.

Xin lỗi nếu cú ​​pháp không hoàn toàn đúng, tôi không phải là lập trình viên Java.

class DaoSingletonFactory
{
    private static Dao dao = null;

    public static Dao getInstance()
    {
        if (DaoSingletonFactory.dao == null) {
            DaoSingletonFactory.dao = new Dao();
        }

        return DaoSingletonFactory.dao;
    }
}

class UsesDao
{
    public void someMethod()
    {
        Dao dao = DaoSingletonFactory.getInstance();
    }
}

Điều này cực kỳ khó kiểm tra, vì bạn không thể trao đổi việc thực hiện mà không thay đổi mã của UsesDao lớp. Điều đó có thể được thực hiện thông qua một số bản vá khỉ , nhưng thường không được coi là một thực hành tốt.

Sau đó, có cách tốt hơn, singleton yếu mẫu , trong đó bạn không truy xuất một thể hiện thông qua một staticphương thức, nhưng làm cho tất cả các lớp phụ thuộc vào thể hiện thông qua một hàm tạo hoặc một setter (trong EventSchedulerServicebạn đang sử dụng phép tiêm setter).

Vấn đề duy nhất là, sau đó bạn cần đảm bảo rằng tất cả các lớp, phụ thuộc vào một thể hiện của lớp chỉ tồn tại một khi vòng đời ứng dụng của bạn, đang lấy cùng một thể hiện như tham số của chúng, nghĩa là. các newđược gọi là chỉ một lần trên đối tượng DAO trong toàn bộ ứng dụng.

Rõ ràng, điều này cực kỳ khó theo dõi và xây dựng đồ thị đối tượng là một công việc tẻ nhạt và khó chịu.

May mắn thay, có các container IoC , làm cho nó dễ dàng hơn nhiều. Ngoài mùa xuân , Guice chứa IoC của Google khá phổ biến đối với các lập trình viên Java.

Khi sử dụng bộ chứa IoC, bạn định cấu hình nó để hành xử theo một cách nhất định, nghĩa là. bạn cho biết nếu nó được xây dựng như thế nào để xây dựng một số lớp nhất định và nếu một số lớp được yêu cầu như là một phụ thuộc, thì phụ thuộc sẽ trông như thế nào (cho dù nó phải luôn là một thể hiện mới hay một singleton) và container chứa tất cả.

Bạn có thể kiểm tra liên kết này để biết ví dụ đơn lẻ với Guice.


Ưu và nhược điểm của việc sử dụng bộ chứa IoC

Ưu

  • tiết kiệm ngân sách bằng cách không phải tự viết tất cả các phương pháp của nhà máy
  • (thường) cấu hình rất đơn giản
  • phát triển nhanh

Nhược điểm

  • phép thuật của phù thủy, các lớp được xây dựng bằng cách nào đó và bạn thực sự không thể thấy nó đã xảy ra như thế nào
  • giảm hiệu suất một chút do tra cứu lớp (các nhà máy được viết thủ công sẽ nhanh hơn một chút)

1

Singleton đang đề cập đến khái niệm chỉ một trường hợp và cách để có quyền truy cập vào thể hiện (thông qua phương thức tĩnh nổi tiếng getInstance () )

Nhưng vẫn còn một ví dụ đằng sau tất cả những điều đó. Một đối tượng được xây dựng với một loại truy cập bị hạn chế.

Trong trường hợp của bạn, tôi muốn đi theo phương pháp DI (tiêm phụ thuộc). Giống như khối mã đầu tiên bạn đã tiếp xúc. Chỉ cần một chút thay đổi. Tiêm DAO thông qua nhà xây dựng. Để loại bỏ hay không các setter là tùy thuộc vào bạn. Nếu bạn muốn bảo vệ Trình điều khiển khỏi những thay đổi trong thời gian chạy thì hãy xóa nó. Nếu bạn muốn cung cấp khả năng như vậy, sau đó giữ nó.

Bạn đã đúng khi sử dụng Giao diện và cung cấp một cửa sổ mở để triển khai thêm DAO. Có thể hoặc không cần thiết. Chỉ mất thêm một phút làm việc, nhưng nó biến thiết kế của bạn linh hoạt. DAO trong bộ nhớ của bạn khá phổ biến. Rất hữu ích như giả tại thời điểm thử nghiệm. Hoặc như triển khai DAO mặc định.

Chỉ là một gợi ý. Tài nguyên tĩnh (đối tượng, phương thức, hằng hoặc biến) giống như tài nguyên toàn cầu. Nếu toàn cầu là xấu xa hay không là vấn đề của nhu cầu hoặc thị hiếu. Tuy nhiên, có những thiếu sót ngầm ràng buộc với họ. Những thứ này liên quan đến đồng thời , an toàn luồng (trong Java, không biết về các ngôn ngữ khác), tuần tự hóa ...

Vì vậy, tôi sẽ đề nghị sử dụng statics một cách thận trọng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.