2015-02-02 3 views
3

В проекте я видел код, написанный бывшим сотрудником. Человек назвал его как реализацию шаблона адаптера, но я не уверен. Вот код:Действительно ли это шаблон адаптера?

public class RowSetAdaptor implements java.io.Serializable { 
    private javax.sql.rowset.CachedRowSet cachedRowSet; 

    public RowSetAdaptor() throw SQLException { 
     cachedRowSet = new com.sun.rowset.CachedRowSetImpl(); 
    } 

    public void populate(ResultSet resultSet) throw SQLException { 
     cachedRowSet.populate(resultSet); 
    } 

    public boolean next() throw SQLException { 
     cachedRowSet.next(); 
    } 

    .... // different methods all using cachedRowSet 
} 

Как я вижу это класс RowSetAdaptor ограничивает доступ к CachedRowSet интерфейсу не все методы CachedRowSet интерфейса доступны в RowSetAdaptor классе. Действительно ли это шаблон адаптера? Если нет, то какой шаблон дизайна используется здесь?

Update [24 февраля 2015]

Благодаря @JB Nizet, @Fuhrmanator, @ Гюнтер Франке, @vikingsteve и @Giovanni Ботта для ваших ответов.

Что делать, если я делаю следующие изменения, чтобы сделать его образцом адаптера?

public interface RowSetI { 
    public boolean next() throws SQLException; 
    ... 
} 

public class CachedRowSetAdapter implements RowSetI { 
    private javax.sql.rowset.CachedRowSet cachedRowSet; 

    public CachedRowSetAdapter() throw SQLException { 
     cachedRowSet = new com.sun.rowset.CachedRowSetImpl(); 
    } 

    public void populate(ResultSet resultSet) throw SQLException { 
     cachedRowSet.populate(resultSet); 
    } 

    public boolean next() throw SQLException { 
     cachedRowSet.next(); 
    } 
    ... 
} 

public class JdbcRowSetAdapter implements RowSetI { 
    private javax.sql.rowset.JdbcRowSet jdbcRowSet; 

    public JdbcRowSetAdapter() throw SQLException { 
     jdbcRowSet = new com.sun.rowset.JdbcRowSetImpl(); 
    } 

    public void populate(ResultSet resultSet) throw SQLException { 
     jdbcRowSet.populate(resultSet); 
    } 

    public boolean next() throw SQLException { 
     jdbcRowSet.next(); 
    } 
    ... 
} 

ТИА

+2

Это не адаптер, так как он не адаптировать интерфейс к другому интерфейсу. Это ... не какая-то картина. –

+0

2 ответы ниже говорят, что это шаблон адаптера. Можете ли вы дать свой ответ о том, почему эти 2 ответа неверны? – srh

+0

IMO, ответ vikingsteve имеет слишком широкую интерпретацию шаблона адаптера. Для меня шаблон адаптера следующий: мне нужно вызвать метод, который принимает интерфейс A в качестве аргумента с экземпляром B, который не реализует A. Поэтому я пишу класс, который реализует A, делегируя объект типа B. В этом смысле, если целью действительно является Сериализуемость, вы можете утверждать, что ответ Джованни верен. Но я не уверен, что это намерение автора. –

ответ

1

Лучший способ проверить, является ли что-то реализацией шаблона, чтобы сопоставить роли/методы в определении GoF для реализации.

GoF Adapter имеет два варианта (адаптер класса и объекта), которые имеют разные структуры. адаптеры класса использовать множественное наследование:

Class adapter

У вас есть класс RowSetAdaptor, что сделало бы его кандидатом на Adapter класса в этой схеме. Однако RowSetAdaptor реализует только Serializable, поэтому я думаю, что это не может быть эта форма шаблона адаптера.

Второй вариант адаптер объекта:

Object Adapter

Опять же, RowSetAdaptor бы быть Adapter класс в этой диаграмме. Похоже, что javax.sql.rowset.CachedRowSet будет адаптированным, поскольку он использует этот класс внутри некоторых своих методов. Тем не менее, самый чистый адаптер GoF должен реализовать некоторый интерфейс Target и , вероятно, обернуть объект Adaptee в его конструкторе (CachedRowSet жестко запрограммирован). Некоторые могут сказать, что Serializable - это интерфейс Target, но это подразумевает, что он будет адаптировать те методы request(). RowSetAdaptor не отменяет ничего в Serializable, что я вижу.

Наконец, если это действительно шаблон адаптера GoF, я бы ожидал, что будет более одного адаптера. Как правило, интерфейс Target разработан, потому что есть некоторые общие функции, которые реализуются различными адаптерами (нет смысла иметь интерфейс только с одной реализацией).

Другим примечательным моментом является то, что Client не должен знать, что он использует RowSetAdaptor; Client видит только объект Target. Трудно обосновать использование интерфейса с клиентом, если клиент просто будет напрямую обращаться к реализации.

Возможно, вы можете проверить код для класса Client или других адаптеров.

Я пришел к выводу, что на основе кода, который вы представили, это не убедительный пример шаблона адаптера GoF.

Других реальных примеров адаптеров на https://stackoverflow.com/a/13323703/1168342

+0

Спасибо. Удивительный ответ. Я думаю, что если я внесу некоторые изменения в коде, он может стать объектным адаптером. Замечания не позволяют много форматирования здесь, поэтому я буду использовать основной вопрос для моих наводящих изменений. Пожалуйста, дайте свой вклад в предлагаемые изменения. – srh

0

Ну класс делает реализации Serializable (она опирается на тот факт, что CachedRowSetImpl является Serializable), так что технически это адаптер. Причина, по которой это необходимо, можно найти here.

Что касается хорошей идеи или нет, это целая другая червь червей (набор результатов может быть огромным, имеет смысл сериализоваться с использованием другого формата, например, json, protobuf и т. Д. .).

+0

Настоящий адаптер адаптирует некоторый метод 'Serializable' - какой метод адаптация адаптера? Кроме того, почему вы ссылаетесь на причину, в которой есть 1 общий голос в качестве вопроса? – Fuhrmanator

+0

@Fuhrmanator Интерфейс «Serializable» - это интерфейс тегов. Он сообщает JVM, что объект может быть сериализован по проводу. Он не добавляет открытый интерфейс к любому объекту, но он использует неявный интерфейс, который [должен быть объявлен приватным] (http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html) в случае пользовательской сериализации. 'ResultSet' не является' Serializable', и причина была четко объяснена в _response_ на этот вопрос (добавлено 3 раза), поэтому этот класс «адаптирует» 'ResultSet' для соответствия интерфейсу __implicit__, указанному' Serializable'. –

+0

@Fuhrmanator, кстати, мы получаем больше семантического аргумента, а не функционального. Мы не знаем, какова цель оригинального автора этого класса и как этот класс используется, поэтому код выглядит довольно открытым для интерпретации. «RowSetAdaptor» реализует только один интерфейс, поэтому, если мы хотим следовать каноническому определению, я чувствую, что это интерфейс, к которому он приспосабливается. Вы можете утверждать, что 'RowSetAdaptor' сам по себе является интерфейсом, хотя и не в смысле java, и поскольку он также женат на реализации, он кажется довольно бесполезным адаптером IMO. –

1

Да, это все еще Адаптер Узор.

Адаптер позволяет два несовместимых интерфейса для совместной работы.

От Java мира, мы привыкли видеть Adapters (например MouseAdapter и MouseListener), которые на самом деле не адаптерами в истинном смысле (поэтому, пожалуйста, быть в курсе, что).

В вашем примере, однако, у адаптера есть намерение уменьшить размер и сложность интерфейса CachedRowSet в новый интерфейс с именем RowSetAdapter, который также является Serializable.

Тот факт, что в данном примере используется состав, а не наследование не исключает его из будучи Adapter картины, я думаю, что это хороший пример Adapter на самом деле, хотя можно также утверждать, что это также представляет Proxy рисунок.

+0

Определение адаптера GoF не является таким широким. Это довольно специфично. Он использует подклассы фиксированного адаптера API. Пример вашего примера MouseAdapter приведен в http://stackoverflow.com/a/9244294/1168342 Для MouseListener это шаблон Observer (например, 'mouseReleased' будет методом, вызываемым при отпускании кнопки мыши [темы]). – Fuhrmanator

+0

Спасибо, я попытаюсь найти ссылку на шаблон адаптера GoF для включения. – vikingsteve

2

Если класс RowSetAdaptor адаптирует интерфейс CachedRowSet каким-либо образом, то RowSetAdaptor можно рассматривать как реализацию адаптер дизайн шаблона (адаптер объекта) в.

Но в вашем примере листинга я не вижу никакой адаптации - операции просто направлены на cachedRowSet объекта - так что клиенты могут получить доступ к интерфейсу с CachedRowSet напрямую.

RowSetAdaptor вводит дополнительный уровень косвенности, который усложняет дизайн и снижает издержки. Его следует использовать только в том случае, если клиенты не могут или не должны напрямую обращаться к интерфейсу CachedRowSet.

«Образец дизайна должен применяться только тогда, когда на самом деле нужна гибкость».
[GoF книга, страница 31]

Примечания: Adapter шаблона проектирования (объект адаптер) предполагает, что клиенты относятся к интерфейсу (Target), чтобы сделать их независимыми от конкретного класса реализации (адаптер).
В вашем примере клиенты ссылаются на (и зависят от) конкретный класс RowSetAdaptor.

Для дальнейшего обсуждения см. Шаблон дизайна шаблонов карт памяти/адаптера GoF по адресу http://w3sdesign.com.

+0

Это цитата из п.31 - это мудрость, которая часто игнорируется. К сожалению, узоры просто слишком проклятые, чтобы их пропустили. – Fuhrmanator

Смежные вопросы