2013-02-15 14 views
6

Próbuję ukryć implementację klasy, której nie mam. Chcę to zrobić, rozszerzając klasę i wdrażając własny interfejs. Oto, jak tworzona jest instancja klasy, której potrzebuję:Java OO: Czy to możliwe?

QueueInfo info = admin.getQueue(queueName); 

KolejkaInfo jest klasą, której nie jestem właścicielem. Aby uzyskać wystąpienie tego obiektu, muszę użyć obiektu admin, aby go uzyskać. Chcę ukryć tę implementację, pracując za pośrednictwem interfejsu o nazwie IQueueInfo. IQueueInfo po prostu da dostęp do tego, czego konsumenci potrzebują od QueueInfo. Aby uzyskać ten QueueInfo, chciałbym pracować poprzez mój własny obiekt o nazwie EMSQueueInfo. Oto jak wyobrażam sobie ten konfigurowania:

public class EMSQueueInfo extends QueueInfo implements IQueueInfo { 
    //... 
} 

Pozwala to moja konsument pracować chociaż interfejs IQueueInfo i pozwala bazowego EMSQueueInfo mieć dostęp do wszystkiego QueueInfo ma. Mój problem polega na uzyskaniu "żywej" instancji QueueInfo. Aby uzyskać regularne wystąpienie QueueInfo, mogę tylko powiedzieć:

QueueInfo info = new QueueInfo(queueName); 

Ten przypadek nie jest „na żywo”, jak w nie został stworzony przez administratora obiektu. Robiąc to:

public class EMSQueueInfo extends QueueInfo implements IQueueInfo { 

    public EMSQueueInfo(String queueName){ 
     super(queueName); 
    } 

} 

nie daje mi obiektu "żywego". To, co chciałbym móc zrobić, to coś takiego:

public class EMSQueueInfo extends QueueInfo implements IQueueInfo { 

    public EMSQueueInfo(String queueName, Admin admin){ 
     super = admin.getQueue(queueName); 
    } 

} 

Ale to niemożliwe.

Jedynym rozwiązaniem widzę jest usunięcie wystaje z mojej klasy EMSQueueInfo i po prostu owijania obiekt w górę siebie, uzyskanie dostępu do wszystkich metod za pośrednictwem prywatnej varialbe:

public class EMSQueueInfo extends QueueInfo implements IQueueInfo { 

    private QueueInfo _queueInfo 

    public EMSQueueInfo(String queueName, Admin admin){ 
     _queueInfo = admin.getQueue(queueName); 
    } 

    public int getMessagesOnQueue() { 
     return _queueInfo.getMessagesOnQueue(); 
    } 

} 

To rozwiązanie działa , ale ja go nienawidzę. Czy ktoś może wymyślić lepszy sposób? Czy próbuję po prostu złamać OO i użyć go niewłaściwie? Ponownie, robię to wszystko, ponieważ chcę, aby konsumenci mogli pracować z IQueueInfo, w przyszłości IQueueInfo może być używany do uzyskiwania dostępu do implementacji JMS QueueInfo lub implementacji QueueInfo MSMQ. Każda pomoc byłaby niesamowita!

+0

Byłbym nieufny wobec rozszerzenia klasy, którą próbujesz ukryć. Nie widzę problemu z kompozycją. –

+0

Metody fabryczne Google – Bohemian

+0

Opisałeś wzorzec 'Adapter': zawijasz coś, aby umożliwić dostęp tylko do niektórych jego części. Więc ** chcesz **, że queueInfo mają być ukryte. W przeciwnym razie ludzie będą mogli uzyskać dostęp do wszystkich pól na tym polu, a nie tylko do tych, które mają. –

Odpowiedz

5

To, co zasugerowałeś, wydaje się całkowicie uzasadnione - nazywa się wzór adaptera (dzięki Martinsos).

Byłoby fajniej, gdybyś w jakiś sposób ukrył obiekt Admin w swojej klasie. Na przykład.

public class EMSQueueInfo implements QueueInfoProvider { 

    private static Admin admin = new Admin(); 
    private QueueInfo queueInfo 

    public EMSQueueInfo(String queueName){ 
     queueInfo = admin.getQueue(queueName); 
    } 

    public int getMessagesOnQueue() { 
     return queueInfo.getMessagesOnQueue(); 
    } 

} 

Próbowałem nadać interfejsowi bardziej "Java" nazwę. Sufiks I jest bardzo .NET. Nie powinno być potrzeby rozszerzania oryginalnej klasy.

może poczuć bolesne wdrożyć jak trzeba mozolnie skopiować tylko ciekawe metody od QueueInfo do swojej QueueInfoProvider, ale ból będzie warto w końcu.

To podejście oddziela aplikację od interfejsu API, nad którym nie masz bezpośredniej kontroli. W tym sensie jest podobny do Facade pattern.

+1

Przepraszam, pochodzę z .NET. Ponownie, nie chcę owijać całej klasy. Powyższe podejście jest tym, czego unikam. getMessagesOnQueue jest już częścią QueueInfo. –

+0

W porządku. Dzięki temu projektowi możesz wybrać, które metody chcesz zawijać. Jeśli to tylko jeden, to w porządku. –

+0

Myślę, że masz rację. Po prostu poczułem trochę brudu, gdy musiałem przerobić wszystko, gdy rozszerzenie klasy wydawało mi się właściwą drogą. –

6

Uważam, że rozwiązanie, którego używasz, które mówisz, że nienawidzisz, jest dobrym rozwiązaniem. Nie łamie OO ani nie wykorzystuje go niewłaściwie.

To, co robisz, to dobrze znany wzorzec o nazwie Adapter pattern (Object Adapter pattern). Jedyną rzeczą, która nie jest potrzebna w twojej klasie, jest rozszerzenie QueueInfo.

+0

Twoja odpowiedź jest również poprawna. Jedynym powodem, dla którego przyjąłem Duncana ponad twoją, jest to, że podał dobry przykład kodu. Dzięki za twoje wejście! –