Stały interfejs

W języku programowania Java wzorzec stałego interfejsu opisuje użycie interfejsu wyłącznie do definiowania stałych, a klasy implementują ten interfejs w celu uzyskania wygodnego dostępu składniowego do tych stałych. Ponieważ jednak stałe są bardzo często jedynie szczegółem implementacji, a interfejsy zaimplementowane przez klasę są częścią eksportowanego API, taka praktyka sprowadza się do umieszczania szczegółów implementacji w API, co zostało uznane za nieodpowiednie np. przez projektanta Javy, Joshuę Blocha . Ogólnie rzecz biorąc, gromadzenie stałych systemowych w klasy niezależne od zachowania może skutkować kiepskim zorientowanym obiektowo , ponieważ często jest to oznaką niskiej spójności . Z tych powodów stałe interfejsy można uznać za antywzorzec .

Użycie tego wzorca ma kilka innych wad: [ oryginalne badania? ]

  1. Zanieczyszcza przestrzeń nazw klas zmiennymi tylko do odczytu, które mogą nie być przydatne.
  2. W przeciwieństwie do taktycznej użyteczności implementacji stałego interfejsu w czasie kompilacji , przypadkowe artefakty w czasie wykonywania mają niewielki praktyczny cel (por. interfejsy znaczników , które również nie mają metod, ale przydatne w czasie wykonywania).
  3. Jeśli w przyszłych wydaniach wymagana jest kompatybilność kodu binarnego, stały interfejs musi na zawsze pozostać interfejsem (nie można go przekształcić w klasę), nawet jeśli nie był używany jako interfejs w konwencjonalnym sensie .
  4. Bez IDE, które rozpoznaje, skąd pochodzą stałe, śledzenie ich z powrotem do zawierającej je klasy lub interfejsu może być czasochłonne.
  5. Instancja interfejsu nie jest składniowo bardziej użyteczna niż sama nazwa interfejsu (ponieważ nie ma metod).
  6. Jeśli programista nie sprawdzi zaimplementowanych interfejsów podczas dodawania stałej do klasy lub nie zrobi tego, ale zrobi literówkę w nazwie dodanej stałej, wartość stałej może zostać zmieniona po cichu. Rozważ przykład 2 poniżej.

Zauważ, że biblioteki Java same używają stałego wzorca interfejsu, co pokazuje, że w niektórych sytuacjach może to być rozsądny wybór.

Przykład 1

   

	   
	   


     

	   
		     
	
 interfejs  publiczny  Stałe  {  double  PI  =  3,14159  ;  podwójna  PLANCK_CONSTANT  =  6,62606896e-34  ;  }  public  class  Obliczenia  implementuje  Stałe  {  public  double  getReducedPlanckConstant  ()  {  return  PLANCK_CONSTANT  /  (  2  *  PI  );  }  } 

Przykład 2

   

	   	  


     

	      	

	       
		
	
 interfejs  publiczny  Stałe  {  public  static  final  int  CONSTANT  =  1  ;  }  public  class  Class1  implementuje  Stałe  {  public  static  final  int  CONSTANT  =  2  ;  // *  public  static  void  main  (  String  args  []  )  zgłasza  wyjątek  {  System  .  na  zewnątrz  println  (  STAŁA  );  }  } 

Przed dodaniem wiersza oznaczonego gwiazdką uruchomienie Class1 drukuje 1. Po dodaniu wiersza Class1 drukuje 2. Obie wersje kompilują się bez ostrzeżeń i błędów.

Alternatywy

Wielu pułapek antywzorca można uniknąć, konwertując stały interfejs na klasę ze statycznymi atrybutami:

    

	  
		
	

	      
	      
 public  final  class  Stałe  {  private  Stałe  ()  {  // ograniczenie tworzenia instancji  }  public  static  final  double  PI  =  3.14159  ;  public  static  final  double  PLANCK_CONSTANT  =  6.62606896e-34  ;  } 

Od wersji Java 5 można użyć importu statycznego , aby móc używać stałych bez kwalifikatora Constants:

 
 

   

	   
		     
	
 importuj stałe  stałe.PLANCK_CONSTANT  ;  importuj statyczne  Stałe.PI  ;  obliczenia  klasy  publicznej  {  public  double  getReducedPlanckConstant  ()  {  return  PLANCK_CONSTANT  /  (  2  *  PI  );  }  } 

Stałe można również importować masowo za pomocą instrukcji import static Constants.* . Osiąga to te same cele, co użycie interfejsu, umożliwiając odwoływanie się do stałych bez kwalifikatora.

W różnym stopniu problemy wymienione powyżej zostały już rozwiązane:

  1. Ponieważ elementy statyczne można importować w określony sposób, przestrzeń nazw klas nie musi być zanieczyszczana wszystkimi elementami stałego interfejsu.
  2. Semantyka czasu wykonywania i kompilacji jest ściślej dopasowana w przypadku korzystania z importu statycznego zamiast stałych interfejsów.
  3. Skompilowany kod ma jedno ograniczenie kompatybilności binarnej mniej (to „obliczenia klasy implementują stałe”).
  4. Ponieważ importy statyczne dotyczą tylko bieżącego pliku (a nie całej hierarchii klas), łatwiej jest wykryć, gdzie zadeklarowano każdy statyczny element członkowski.
  5. Nie ma potrzeby deklarowania zmiennych o stałym typie interfejsu i jest potencjalnie jaśniejsze, że w rzeczywistości nie istnieje żadna konkretna instancja.

Należy jednak zauważyć, że zmiany nie poprawiają spójności klasy Constants ani nie zapobiegają przypadkowej cichej modyfikacji wartości stałej, więc import statyczny nie powinien być uważany za panaceum.