Bir DAO tek başına mı olmalı?


14

RESTful API geliştiriyorum ve kaynaklarım için DAO'ları kullanmanın uygun olduğunu düşünüyorum çünkü bunları saklamak için sadece bellek kullanmayı planlasam da, kullanmaya karar verdiyse kütüphanemi kullananlara bir kapıyı kapatmak istemiyorum DAO için bir veritabanı uygulaması.

Benim sorum DAO'nun singleton olup olmayacağı. Değilse, hizmet DAO'nun bir örneğine sahip olacak ve kabaca şu şekilde görünecektir:

@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 bir singleton olsa da, sanırım sadece ilk satırda çok fazla bir fark olmaz:

private IEventSchedulerDao dao = EventSchedulerDao.getInstance();

Yine de bir IEventSchedulerDaoörnek kullanmak zorunda kalacağım , ama sanırım tüm singletonlar bu şekilde çalışıyor mu? Nedense, her zaman tekilleri statik yöntemlerle ilişkilendiririm, bu yüzden kullanıcı tarafından görülebilen tekli bir örneğe sahip olmak yerine getInstance(), bu gizli olur ve EventSchedulerDao.get(name)statik bir şekilde vb. Bu bir şey mi yoksa bu sadece ben mi?

Yani, singleton DAO'ları olmalı mı yoksa olmamalı mı?

Ve bir yan soru olarak, kullanıcının kendi DAO'larını uygulaması için açık kapılara sahip olmak yaklaşımım iyi mi?


Statik erişimli bir singleton yerine IoC singleton kullanabilirsiniz.
CodesInChaos

Yanıtlar:


10

Singleton kullanmazdım. Tanınmış bir anti-modeldir ve testi zorlaştırır. Somut bir uygulamaya daha çok enjekte ederim ve hizmetinizin bir DAO arabirimine başvurmasını sağlarım (farklı uygulamaları enjekte etmenize izin verir)


1
Son cümlede önerdiğin şey tam olarak doğru yaptığım şey mi?
dabadaba

1
Bir arayüz üzerinden referansta bulunuyorsunuz (evet), ancak DAO'yu enjekte etmiyorsunuz (açık olmak için ....)
Brian Agnew

Ne demek istiyorsun? Bunun için bir pasörüm var değil mi?
dabadaba

@dabadaba Çizgi private IEventSchedulerDao dao = new EventSchedulerDao();yanlış yaptığınız yerdir. İçin uygulama IEventSchedulerDaoyapıcı yoluyla enjekte edilmeli ve asla değiştirilmemelidir (yani, ondan da kurtulmalıdır setEventSchedulerDao).
David Arno

Tamam anladım. Ben sadece varsayılan bir DAO sağlamak için yaptım ve değiştirmek "isteğe bağlı" olacaktır. Ancak önerinizi almak, hizmet için varsayılandan farklı bir kurucuya sahip olmak anlamına gelir ve honly, varsayılan kurucuyu kullandığından Jersey ile nasıl çalıştığı hakkında hiçbir fikrim yok. Bunu nasıl yapacağınızı biliyor musunuz?
dabadaba

4

A D ata A Dışı Erişim Ç Nesne sadece gerçekten uygulamanızda bir kez bulunmalıdır. Mantık aynı kalır, farklı olan tek şey DAO'nun sağladığı yöntemlere giren ve çıkan değerlerdir.

Bunu göz önünde bulundurarak, açık bir şekilde, genellikle gerçekleşen ilk şey, DAO'yu güçlü bir singleton olarak uygulamaktır , yani staticbir fabrika sınıfında bir yönteme sahip olduğunuzda, getInstanceDAO'nun boş olması durumunda tembel bir şekilde yüklenmesi ve döndürülmesi gibi bir şey.

Sözdizimi tam olarak doğru değilse, affedersiniz, ben bir Java programcısı değilim.

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

Bunu test etmek inanılmaz derecede zordur, çünkü UsesDaosınıfın kodunu değiştirmeden uygulamayı değiştiremezsiniz . Bu, bazı maymun yamalarıyla yapılabilir , ancak genellikle iyi bir uygulama olarak kabul edilmez.

Sonra iyi bir yol yoktur zayıf tekil bir arayüz aracılığıyla bir örneğini almak yok desen, staticyöntemin, ancak (sizin de bütün sınıflar bir yapıcısı veya setter yoluyla ya örneğine bağlı hale EventSchedulerServiceEğer ayarlayıcı enjeksiyon kullandığınız).

Tek sorun, daha sonra, yalnızca uygulama yaşam döngünüzün ardından var olması gereken bir sınıf örneğine bağlı olan tüm sınıfların, parametreleriyle aynı örneği aldığından emin olmanız gerekir. newTüm uygulamada DAO nesne üzerinde yalnızca bir kez denir.

Açıkçası, bunu izlemek inanılmaz derecede zordur ve nesne grafiğini oluşturmak sıkıcı ve can sıkıcı bir iştir.

Neyse ki, IoC kapları var, bu da çok daha kolay. Spring'in yanı sıra , Google'ın Guice IoC konteyneri Java programcıları arasında oldukça popülerdir.

Bir IoC kapsayıcısını kullanırken, belirli bir şekilde davranacak şekilde yapılandırırsınız. belirli sınıfların nasıl oluşturulacağı ve bir sınıfın bağımlılık olarak gerekli olup olmadığı, bağımlılığın nasıl görünmesi gerektiğini (her zaman yeni bir örnek mi yoksa tekil mi olması gerektiğini) anlatırsınız ve kap her şeyi birbirine bağlar.

Guice ile tek bir örnek için bu bağlantıyı kontrol edebilirsiniz .


IoC kapsayıcı kullanmanın artıları ve eksileri

Artıları

  • Tüm fabrika yöntemlerini kendiniz yazmak zorunda kalmadan bütçeden tasarruf etmek
  • (genellikle) çok basit yapılandırma
  • hızlı gelişme

Eksileri

  • bir büyücünün büyüsü, sınıflar bir şekilde inşa edilmiş ve nasıl olduğunu gerçekten göremiyorsunuz
  • sınıf araması nedeniyle küçük bir performans düşüşü (elle yazılmış fabrikalar biraz daha hızlı olacaktır)

1

Singleton , konsepte sadece bir örnek ve örneğe erişmenin yolunu ifade ediyor (çok ünlü statik yöntem getInstance () aracılığıyla )

Ama yine de bunların arkasında bir örnek var. Bir çeşit kısıtlı erişime sahip inşa edilmiş bir nesne.

Sizin durumunuzda DI yaklaşımını tercih ederim (bağımlılık enjeksiyonu). Gösterdiğiniz ilk kod bloğu gibi. Sadece küçük bir değişiklik. DAO'yu yapıcı yoluyla enjekte edin. Ayarlayıcıyı çıkarmak ya da almamak size kalmış. Denetleyiciyi çalışma süresindeki değişikliklerden korumak istiyorsanız, kaldırın. Böyle bir olasılık sunmak istiyorsanız, o zaman saklayın.

Bir Arayüz kullanma ve daha ileri DAO uygulamaları için açık bir pencere sunma hakkına sahipsiniz. Gerekebilir veya gerekmeyebilir. Sadece bir dakika daha fazla iş gerektirir, ancak tasarımınızı esnek hale getirir. Sizin hafıza DAO oldukça yaygındır. Test zamanında sahte olarak çok yararlı . Veya varsayılan DAO uygulaması olarak.

Sadece bir ipucu. Statik kaynaklar (nesneler, yöntemler, sabitler veya değişkenler) küresel kaynaklar gibidir. Eğer küreseller kötüyse ya da değil ise ihtiyaçlar ya da zevkler meselesidir. Ancak bunlara bağlı örtük eksiklikler var. Bunlar eşzamanlılık , iş parçacığı güvenliği (Java'da, diğer diller hakkında bilmiyorum), serileştirme ...

Bu yüzden statiği dikkatli bir şekilde kullanmanızı öneririm

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.