2016-01-04 4 views
2

Я разрабатываю API, который определяет общий интерфейс между двумя разными моделями. Общий интерфейс - это Peer, который представляет собой внешнюю систему для связи. A Client - это Peer, который пытается установить соединение с определенным адресом. И Server - это Peer, который принимает соединения из подсети адресов.Расширяемый интерфейс для разных моделей

public interface Peer { 
    void send(Message m); 
} 

public interface Client extends Peer { 
    InetAddress getAddress(); 
} 

public interface Server extends Peer { 
    String getSubnet(); 
} 

Приложения, использующие этот API будет работать с Peer объектами. Из-за этого их логика будет постоянно требовать проверки типа, чтобы извлекать информацию, уникальную для Peer, для выполнения их работы. Кроме того, если когда-либо появлялся другой тип приложений Peer, это может сломаться.

Peer p = incomingMessage.getPeer(); 

if (p instanceof ClientPeer) { 
    //do client peer stuff 
} else if (p instanceof ServerPeer) { 
    //do server peer stuff 
} else { 
    //uh oh... 
} 

Есть ли более чистый способ спроектировать это? Тот, который не требует постоянной проверки типа и не имеет недостатка в дальнейшем расширении с новыми типами Peer?

+1

Возможно, ClientPeer и ServerPeer должны делать свои собственные вещи, или, возможно, им не нужны подтипы одноранговых узлов, если они всегда делают разные вещи. – dbugger

ответ

0

код клиента не должен выполнять инструкции switch, подобные этому https://en.wikipedia.org/wiki/Proxy_pattern - это подход, который вы, возможно, захотите реализовать.

Имейте интерфейс «peer», который имеет некоторые абстрактные методы. Затем создайте фабрику/фабрику, которая «создает» экземпляр партнера, которого они хотят. Затем вы сохраняете это как свою переменную «peer». Таким образом, клиенту нужно только изучить 1 API («сверстников») и не заботиться обо всех разных типах сверстников.

Однако, @dbugger правильно, если API для «клиента» и «сервера» настолько отличаются от того, что они не должны расширять один и тот же класс/интерфейс. Если у них есть СУБЪЕКТЫ методов, которые перекрываются, тогда создайте более ограниченный интерфейс, который касается этой функциональности.

Это звучит как сценарий типа бит-торрент, а «серверы» в BT не являются клиентами. Они могут запускать клиентский код, но это отдельный процесс, выполняющийся на одном компьютере, а не на сервере. (это может помочь вам очистить логику того, что такое «peer»)

0

Приложения, использующие этот API, будут работать с объектами Peer. Из-за этого их логика будет постоянно требовать проверки типа, чтобы извлекать информацию, уникальную для Peer, для выполнения своей работы.

Если это так, они не работают с одноранговыми объектами или api Peer должны быть перепроектированы, потому что им нужна информация, которую не предоставляет сверстник.

Обычно вы обходите это путем извлечения общего api и перевода условного кода в подклассы. Например.

public class ClientPeer implements Client { 

    public void findAGoodName(){ 
     //do client peer stuff 
    } 
} 

Иногда вы попадаете в ситуацию, что «сделать клиента пэра вещи» необходима информация, вызывающая только метод имеет. В этом случае ввести другой интерфейс. Например.

public class ClientPeer implements Client { 

    public void findAGoodName(CallerData callerData){ 
     //do client peer stuff 
    } 
} 

PS: Найти хорошие имена для классов, методов и так далее.

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