DAO는 싱글 톤이어야합니까?


14

RESTful API를 개발 중이며 DAO를 리소스에 사용하는 것이 편리하다고 생각합니다. 메모리를 사용하여 저장하려고 계획하고 있지만 사용하기로 결정한 경우 내 라이브러리를 사용하는 사람에게 문을 닫고 싶지 않기 때문에 DAO를위한 데이터베이스 구현.

내 질문은 DAO가 싱글 톤이어야하는지 아닌지입니다. 그렇지 않은 경우 서비스에 DAO 인스턴스가 있으며 대략 다음과 같습니다.

@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);
    }
}

DAO가 싱글 톤이라면 첫 번째 줄에 큰 차이는 없을 것입니다.

private IEventSchedulerDao dao = EventSchedulerDao.getInstance();

나는 여전히 IEventSchedulerDao인스턴스 를 사용해야 하지만 모든 싱글 톤이 이와 같이 작동 한다고 생각합니까? 어떤 이유로 나는 항상 싱글 톤을 정적 메소드와 상관 관계가 있으므로 사용자에게 싱글 톤 인스턴스를 표시하는 대신 getInstance()숨겨져 EventSchedulerDao.get(name)서 정적 방식으로 등을 사용 합니다. 이거 아니면 나인가요?

그렇다면 싱글 톤 DAO가 있어야합니까?

그리고 부수적 인 질문으로, 사용자가 자신의 DAO를 구현할 수 있도록 문을 여는 것이 괜찮습니까?


정적 접근자가있는 싱글 톤 대신 IoC 싱글 톤을 사용할 수 있습니다.
코드 InChaos

답변:


10

나는 싱글 톤을 사용하지 않을 것입니다. 잘 알려진 안티 패턴 이며 테스트를 어렵게 만듭니다. 오히려 구체적인 구현에 주입 하고 서비스에서 DAO 인터페이스를 참조하도록하십시오 (다른 구현을 주입 할 수 있도록 허용)


1
마지막 문장에서 제안하는 것은 정확히 내가 옳은 일입니까?
dabadaba 2016 년

1
당신은 (예) 인터페이스를 통해 참조하고,하지만 당신은하지 않을 주입 (.... 명확하게하기 위해)이 DAO는
브라이언 애그뉴

무슨 소리 야? 나는 세터를 가지고 있지 않습니까?
dabadaba

@dabadaba 줄 private IEventSchedulerDao dao = new EventSchedulerDao();이 잘못되었습니다. 에 대한 구현 IEventSchedulerDao은 생성자를 통해 주입되어야하며 절대 변경되지 않아야합니다 (즉, 제거 setEventSchedulerDao).
David Arno

알았어요 방금 기본 DAO를 제공하고 "선택적"으로 변경하는 작업을 수행했습니다. 그러나 제안을하는 것은 서비스 생성자를 기본값과 다른 것을 의미하며, 기본 생성기를 사용하기 때문에 Jersey와 어떻게 작동하는지 잘 모르겠습니다. 우연히 그렇게하는 방법을 알고 있습니까?
dabadaba 2016 년

4

D ATA CCESS O bject 만 정말 응용 프로그램에서 한 번 있어야합니다. 논리는 동일하게 유지되며 DAO가 제공하는 방법으로 들어오고 나가는 값만 다릅니다.

그것을 염두에두고, 분명히 일반적으로 발생하는 첫 번째 일은 DAO를 강력한 싱글 톤 으로 구현하는 것입니다. 즉 static, 팩토리 클래스에 메소드 가있을 때 와 같이 getInstanceDAO의 인스턴스가 null 인 경우 게으른로드하고 반환합니다.

구문이 완전히 맞지 않으면 실례합니다. 저는 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();
    }
}

UsesDao클래스 코드를 변경하지 않고 구현을 교체 할 수 없기 때문에 테스트하기가 매우 어렵습니다 . 이것은 일부 원숭이 패치를 통해 수행 할 수 있지만 일반적으로 좋은 습관으로 간주되지는 않습니다.

그런 다음 더 나은 방법, 약한 싱글 톤 패턴이 있습니다. 여기서 static메소드 를 통해 인스턴스를 검색하지 않지만 모든 클래스가 생성자 또는 세터 ( EventSchedulerService세터 주입을 사용하는) 를 통해 인스턴스에 종속되도록하십시오 .

유일한 문제는 응용 프로그램 수명주기에 한 번만 존재해야하는 클래스의 인스턴스에 의존하는 모든 클래스가 해당 매개 변수와 동일한 인스턴스를 사용하고 있는지 확인해야한다는 것입니다. 은 new전체 응용 프로그램에서 DAO 객체에 한 번만 호출됩니다.

분명히, 이것은 객체 그래프를 추적하고 구성하는 것이 매우 어렵고 지루하고 성가신 작업입니다.

운 좋게도 IoC 컨테이너가있어 훨씬 쉬워졌습니다. Spring 외에도 Google 의 Guice IoC 컨테이너는 Java 프로그래머에게 인기가 있습니다.

IoC 컨테이너를 사용하는 경우 특정 방식으로 작동하도록 구성합니다. 특정 클래스를 구성하는 방법과 종속성으로 일부 클래스가 필요한 경우 종속성이 어떻게 보이는지 (항상 새 인스턴스인지 단일 인스턴스인지 여부) 컨테이너가 모두 연결됩니다.

Guice를 사용 하여이 링크 에서 싱글 톤 예제를 확인할 수 있습니다 .


IoC 컨테이너 사용의 장단점

찬성

  • 모든 팩토리 메소드를 직접 작성할 필요가 없으므로 예산 절약
  • (보통) 매우 간단한 구성
  • 빠른 개발

단점

  • 마법사의 마술, 클래스는 어떻게 든 구성되어 있으며 실제로 어떻게 발생했는지 알 수 없습니다.
  • 클래스 조회로 인한 약간의 성능 저하 (수동으로 작성된 팩토리는 약간 빠름)

1

Singleton하나의 인스턴스 만 개념 과 인스턴스에 액세스하는 방법 ( 고명 한 정적 메소드 getInstance () )을 참조합니다.

그러나 여전히 그 모든 것 뒤에 인스턴스가 있습니다. 일종의 resticted access를 가진 내장 객체.

귀하의 경우에는 DI 접근 (종속 주입)을 원합니다. 첫 번째 코드 블록처럼 노출했습니다. 약간의 변화. 생성자를 통해 DAO를 주입하십시오. 세터를 제거할지 여부는 귀하에게 달려 있습니다. 런타임에서 컨트롤러가 변경되는 것을 방지하려면 제거하십시오. 그러한 가능성을 제공하려면 유지하십시오.

인터페이스를 사용하고 추가 DAO 구현을위한 열린 창을 제공합니다. 필요하거나 필요하지 않을 수 있습니다. 단 1 분만 더 작업 할 수 있지만 디자인이 유연 해집니다. 당신 의 기억 DAO 는 매우 일반적입니다. 테스트 시간에 모형으로 매우 유용 합니다. 또는 기본 DAO 구현으로.

힌트 만. 정적 리소스 (객체, 메서드, 상수 또는 변수)는 전역 리소스와 같습니다. 세계가 악한 지 여부는 필요 나 취향의 문제입니다. 그러나 내재 된 단점이 있습니다. 이것들은 동시성 , 스레드 안전성 (Java에서는 다른 언어에 대해 모른다), 직렬화와 관련이 있습니다 ...

정적을 조심스럽게 사용하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.