2017-02-07 17 views
3

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

Рассмотрите возможность добавления статических методов интерфейса, чтобы позволить клиентскому коду создавать (потенциально специализированные) объекты, реализующие интерфейс. Например, если у нас есть интерфейс Point с двумя методами int x() и int y(), то мы можем выставить статический метод Point.of (int x, int y) , который создает (скрытую) реализацию интерфейс.

Таким образом, если х и у равны нулю, то мы можем вернуть специальную реализацию класс PointOrigoImpl (без х или у полей), либо мы возвращаем другой класс PointImpl, который удерживает заданную х и у значения. Обеспечьте , что классы реализации находятся в другом пакете, который явно не является частью API (например, поместите интерфейс Point в com.company. Product.shape и реализации в com.company.product.internal.shape) ,

Do This:

Point point = Point.of(1,2);

Не делайте этого:

Point point = new PointImpl(1,2);

Преимущество в том, что это усиливает инкапсуляция? Однако, если реализация является частной, а не частью API, это не создаст проблем с доступом? Если клиент, «мир», как здесь:

https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

не имеет доступа к реализации Point то, как это может возможно создать экземпляр нового Point, как описано выше для «сделать это»?

ответ

2

Например, если мы имеем точку интерфейса с двумя методами (INT х) и Int у(), то мы можем выставить статический метод Point.of (Int х, Int у) , который производит (скрытая) реализация интерфейса.

1) Помните, что с Java 8 вы можете добавить статический метод в интерфейс, но прежде чем вы не сможете.

2) У меня есть некоторые трудности, чтобы понять этот совет:

Таким образом, если х и у равны нулю, то мы можем вернуть специальную реализацию класса PointOrigoImpl (без х или у полей), или иначе мы возвращаем еще один класс PointImpl, который содержит заданные значения x и y. Обеспечьте , что классы реализации находятся в другом пакете, который явно не является частью API (например, поместите интерфейс Point в com.company. Product.shape и реализации в com.company.product.internal.shape) ,

Вот пример Point класс, который соответствует тексту вы ссылаетесь:

package com.company.product.shape; 

import com.company.product.internal.shape.PointOrigoImpl; 
import com.company.product.internal.shape.PointImpl; 

public interface Point{ 
    int x(); 
    int y();  
    static Point of(int x, int y) { 
     if (x == 0 && y == 0){ 
     return new PointOrigoImpl(); 
     } 
     return new PointImpl(x, y); 
    } 
} 

Если интерфейс Point предоставляется клиентам, и что он объявляет фабричный метод, компилировать штраф, Point интерфейс должен обязательно иметь видимость для классов PointOrigoImpl и PointImpl, чтобы создать их.

В интерфейсе Point и подклассов в двух различных пакетах (com.company.product.shape и com.company.product.internal.shape), , что означает, что PointImpl и PointOrigoImpl должен иметь открытый конструктор иначе Point не может создать экземпляр их.
Наконец, клиенты, которые манипулируют Точками, могут также создавать экземпляр конструктора подклассов PointImpl и PointOrigoImpl.

Это поражает цель фабрики, которая не хочет раскрывать реализацию, чтобы выбрать себе реализацию для возврата.

Интерфейс является общедоступным и предназначен для полного доступа к клиенту.
Так как общее правило не должно содержать реализаций, которые мы не хотим предоставлять клиентам.

3) Здесь:

Преимущество в том, что это усиливает инкапсуляция? Однако, если реализация является частной, а не частью API, является ли этот пакет не создавать проблемы с доступом? Если клиент, «мир», как здесь: не имеет доступа к реализации Point, то как это может быть , возможно, создать экземпляр нового Точка, как указано выше, для «сделать это»?

Я полагаю, вы удивляетесь, почему текст говорит: Убедитесь, что классы реализации находятся в другом пакете, которые явно не является частью API.

В тексте вы ссылаетесь, автор хочет, чтобы интерфейс быть известен Point клиентами, но он не хочет подклассы Point известен, потому что он хочет, чтобы решить точки подкласса для возврата в соответствии с параметром используемого в заводской точке.

Точечные клиенты будут знать только этот интерфейс.

В Java для того, чтобы не предоставление доступа к классам реализации вы можете использовать общественный класс, интерфейс и внутренний частный класс:

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

На примере, на который вы ссылаетесь, это было бы прямо.

Point (интерфейс):

public interface Point{ 
    int x(); 
    int y();    
} 

Пойнт завод (общественный класс, который содержит частные классы):

public final class PointFactory { 

    // private classes 
    private class PointImpl implements Point { 

     private int x; 
     private int y; 

     private PointImpl(int x, int y) { 
      this.x = x; 
      this.y = y; 
     } 

     public int x() { 
      return x; 
     } 

     public int y() { 
      return y; 
     } 
    } 

    private class PointOrigoImpl implements Point { 

     public int x() { 
      return 0; 
     } 

     public int y() { 
      return 0; 
     } 
    } 

    // end private classes 

    public Point of(int x, int y) { 
     if (x == 0 && y == 0) { 
      return new PointOrigoImpl(); 
     } 
     return new PointImpl(x, y); 
    } 

} 
1

Ну PointImpl также мог бы открыть API для создания себя, возможно, в форме PointImpl.create(int x, int y) и PointOrigoImpl.create(). Поскольку они находятся во внутреннем пакете, они могут быть общедоступными, и Point.of могут использовать их свободно, а технически «скрыты» от пользователя API, поскольку они оставлены в com.company.product.internal.shape.

Конечно, это работает на добросовестности, что программист не будет злоупотреблять PointImpl.create вместо Point.of, но это нормально. Если программист хочет разорвать инкапсуляцию (или нуждается в этом), его вообще не остановить (как и должно быть).

0

Если клиент, «мир» не имеет доступа к реализации Point, то как он может создать экземпляр новой точки, как указано выше, для «сделать это»?

Клиент не должен создавать экземпляр при создании экземпляра в самом Point. И в качестве реализации implements интерфейс Point, все доступные для общественности методы Point должны быть доступны клиенту, а клиент всегда может свободно играть с этими методами.