"정적 팩토리"방법은 무엇입니까?
"정적 팩토리"방법은 무엇입니까?
답변:
데이터베이스 연결은 리소스를 많이 사용하기 때문에 데이터베이스 연결에 직접 액세스 할 수 없습니다. 따라서 우리 getDbConnection
가 한계 미만이면 연결을 만드는 정적 팩토리 메소드 를 사용합니다. 그렇지 않으면 "예비"연결을 제공하려고하지만 예외가 없으면 실패합니다.
public class DbConnection{
private static final int MAX_CONNS = 100;
private static int totalConnections = 0;
private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();
private DbConnection(){
// ...
totalConnections++;
}
public static DbConnection getDbConnection(){
if(totalConnections < MAX_CONNS){
return new DbConnection();
}else if(availableConnections.size() > 0){
DbConnection dbc = availableConnections.iterator().next();
availableConnections.remove(dbc);
return dbc;
}else {
throw new NoDbConnections();
}
}
public static void returnDbConnection(DbConnection dbc){
availableConnections.add(dbc);
//...
}
}
정적 팩토리 메소드 패턴 캡슐 오브젝트 작성하는 방법이다. 팩토리 메소드가 없으면 클래스의 생성자를 직접 호출하면 됩니다 Foo x = new Foo()
. 이 패턴을 사용하면 팩토리 메소드를 대신 호출합니다 Foo x = Foo.create()
. 생성자는 private으로 표시되므로 클래스 내부를 제외하고는 호출 할 수 없으며 팩토리 메소드는 static
먼저 객체가 없어도 호출 할 수 있도록 표시됩니다 .
이 패턴에는 몇 가지 장점이 있습니다. 하나는 팩토리가 많은 서브 클래스 (또는 인터페이스의 구현 자) 중에서 선택하여이를 리턴 할 수 있다는 것입니다. 이런 식으로 호출자는 잠재적으로 복잡한 클래스 계층을 알거나 이해할 필요없이 매개 변수를 통해 원하는 동작을 지정할 수 있습니다.
Matthew와 James가 지적했듯이 연결과 같은 제한된 리소스에 대한 액세스를 제어하는 또 다른 이점이 있습니다. 이 방법 은 재사용 가능한 객체의 풀 을 구현하는 방법 입니다. 객체를 생성 , 사용 및 분해하는 대신 구성 및 파괴가 고가의 프로세스 인 경우 한 번 구축하여 재활용하는 것이 더 합리적입니다. 팩토리 메소드는 기존의 사용되지 않는 인스턴스화 된 오브젝트가있는 경우이를 리턴하거나 오브젝트 수가 임계 값보다 낮은 null
경우이를 생성 하거나 예외를 발생 시키거나 상위 임계 값을 초과하면 리턴 할 수 있습니다.
Wikipedia의 기사에 따르면 여러 팩토리 메소드는 유사한 인수 유형에 대한 다른 해석을 허용합니다. 일반적으로 생성자는 클래스와 이름이 동일하므로 주어진 서명을 가진 생성자를 하나만 가질 수 있습니다 . 팩토리는 제한이 없으므로 동일한 인수 유형을 허용하는 두 가지 다른 메소드를 가질 수 있습니다.
Coordinate c = Coordinate.createFromCartesian(double x, double y)
과
Coordinate c = Coordinate.createFromPolar(double distance, double angle)
Rasmus가 지적한 것처럼 가독성을 향상시키는 데에도 사용할 수 있습니다.
노트! " 정적 팩토리 메소드 는 팩토리 메소드 패턴 과 동일 하지 않습니다 "(c) Effective Java, Joshua Bloch.
팩토리 메소드 : "객체를 생성하기위한 인터페이스를 정의하지만 인터페이스를 구현하는 클래스가 인스턴스화 할 클래스를 결정하게합니다. 팩토리 메소드는 클래스가 서브 클래스에 대한 인스턴스화를 연기하게합니다"(c) GoF.
"정적 팩토리 메소드는 단순히 클래스의 인스턴스를 리턴하는 정적 메소드입니다." (c) 효과적인 Java, Joshua Bloch. 일반적으로이 메소드는 특정 클래스 내에 있습니다.
차이점:
정적 팩토리 메소드의 핵심 아이디어는 객체 생성을 제어하고 생성자에서 정적 메소드로 위임하는 것입니다. 생성 될 객체의 결정은 메소드 외부에서 만들어진 추상 팩토리 (일반적인 경우는 아니지만)에서와 같습니다. Factory Method의 핵심 (!) 아이디어는 Factory Method 내에서 생성 할 클래스의 인스턴스에 대한 결정을 위임하는 것입니다. 예를 들어 고전적인 Singleton 구현은 정적 팩토리 메소드의 특별한 경우입니다. 일반적으로 사용되는 정적 팩토리 메소드의 예 :
정적 팩토리 메소드로 가독성을 향상시킬 수 있습니다.
비교
public class Foo{
public Foo(boolean withBar){
//...
}
}
//...
// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.
에
public class Foo{
public static Foo createWithBar(){
//...
}
public static Foo createWithoutBar(){
//...
}
}
// ...
// This is much easier to read!
Foo foo = Foo.createWithBar();
private Foo(boolean withBar){/*..*/}
public static Foo createWithBar(){return new Foo(true);}
public static Foo createWithoutBar(){return new Foo(false);}
- 코드를 명확히 할 수있는 생성자와 달리 이름이 있습니다.
- 호출 할 때마다 새 객체를 만들 필요가 없습니다. 필요한 경우 객체를 캐시하고 재사용 할 수 있습니다.
- 반환 유형의 하위 유형을 반환 할 수 있습니다. 특히 구현 클래스가 호출자에게 알려지지 않은 개체를 반환 할 수 있습니다. 이것은 인터페이스를 정적 팩토리 메소드의 리턴 유형으로 사용하는 많은 프레임 워크에서 매우 유용하고 널리 사용되는 기능입니다.
그것은 모두 유지 보수성으로 귀결됩니다. 이것을 넣는 가장 좋은 방법은 new
키워드를 사용하여 객체를 만들 때마다 구현하는 코드를 연결하는 것입니다.
팩토리 패턴을 사용하면 객체를 만드는 방식과 객체를 만드는 방식을 분리 할 수 있습니다. 생성자를 사용하여 모든 객체를 만들면 본질적으로 객체를 사용하는 코드를 해당 구현에 연결해야합니다. 객체를 사용하는 코드는 해당 객체에 "종속"됩니다. 이것은 표면 상 큰 문제가 아닌 것처럼 보일 수 있지만 객체가 변경 될 때 (생성자의 서명을 변경하거나 객체를 서브 클래 싱하는 것을 고려할 때) 돌아가서 모든 곳에서 사물을 다시 연결해야합니다.
오늘날 공장은 자체 유지하기가 약간 어려운 보일러 플레이트 코드가 많이 필요하기 때문에 Dependency Injection을 선호하여 크게 솔질되었습니다. Dependency Injection은 기본적으로 팩토리와 동일하지만 구성 또는 주석을 통해 객체를 선언적으로 연결하는 방법을 지정할 수 있습니다.
클래스의 생성자가 private 인 경우 클래스 외부에서 클래스의 객체를 만들 수 없습니다.
class Test{
int x, y;
private Test(){
.......
.......
}
}
우리는 클래스 외부에서 객체를 만들 수 없습니다. 따라서 클래스 외부에서 x, y에 액세스 할 수 없습니다. 그렇다면이 수업의 용도는 무엇입니까?
답변 : FACTORY 메소드 는 다음과 같습니다 .
위 클래스에서 아래 메소드를 추가하십시오.
public static Test getObject(){
return new Test();
}
이제 외부에서이 클래스에 대한 객체를 만들 수 있습니다. 길처럼 ...
Test t = Test.getObject();
따라서 개인 생성자를 실행하여 클래스의 객체를 반환하는 정적 메서드를 FACTORY 메서드 라고
합니다.
Static Factory Method
공공 생성자보다 이점이 있습니까?
나는 내가 아는 것에 대해이 게시물에 약간의 빛을 추가 할 것이라고 생각했습니다. 우리는이 기술을 광범위하게 사용했습니다 recent android project
. 대신 클래스를 인스턴스화하는 데 creating objects using new operator
사용할 수도 있습니다 static method
. 코드 목록 :
//instantiating a class using constructor
Vinoth vin = new Vinoth();
//instantiating the class using static method
Class Vinoth{
private Vinoth(){
}
// factory method to instantiate the class
public static Vinoth getInstance(){
if(someCondition)
return new Vinoth();
}
}
정적 메소드는 조건부 객체 생성을 지원합니다 . 생성자를 호출 할 때마다 객체가 생성되지만 원하지 않을 수도 있습니다. 조건 만 확인한 다음 새 객체를 생성한다고 가정합니다. 조건이 충족되지 않으면 매번 Vinoth의 새 인스턴스를 생성하지 않습니다.
Effective Java 에서 가져온 또 다른 예 .
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
이 메소드는 부울 프리미티브 값을 부울 오브젝트 참조로 변환합니다. 이 Boolean.valueOf(boolean)
방법은 우리를 설명하며 결코 객체를 생성하지 않습니다. static factory methods
반복에서 동일한 객체를 반환하는 기능을 invocations
통해 클래스는 언제든지 존재하는 인스턴스를 엄격하게 제어 할 수 있습니다.
Static factory methods
와 달리 모든 반환 유형 중 하나를 constructors
반환 할 수 있습니다 . 이러한 유연성의 한 가지 적용은 API가 클래스를 공개하지 않고도 객체를 반환 할 수 있다는 것입니다. 이러한 방식으로 구현 클래스를 숨기면 매우 컴팩트 한 API가됩니다.object
subtype
Calendar.getInstance ()는 그것은 로케일에 따라 생성하고, 위의 좋은 예입니다 BuddhistCalendar
, JapaneseImperialCalendar
또는 기본 하나 Georgian
.
내가 생각할 수있는 또 다른 예는 Singleton pattern
생성자를 비공개로 만들면 getInstance
항상 사용할 수있는 인스턴스가 하나뿐이라는 고유 한 메서드를 만듭니다.
public class Singleton{
//initailzed during class loading
private static final Singleton INSTANCE = new Singleton();
//to prevent creating another instance of Singleton
private Singleton(){}
public static Singleton getSingleton(){
return INSTANCE;
}
}
팩토리 메소드는 객체의 인스턴스화를 추상화하는 메소드입니다. 일반적으로 팩토리는 일부 인터페이스를 구현하는 클래스의 새 인스턴스가 필요하지만 구현 클래스를 모르는 경우 유용합니다.
이것은 관련 클래스의 계층 구조로 작업 할 때 유용합니다. 이에 대한 좋은 예는 GUI 툴킷입니다. 각 위젯의 구체적인 구현을 위해 생성자에 대한 호출을 단순히 하드 코딩 할 수 있지만 한 툴킷을 다른 툴킷으로 바꾸고 싶다면 변경해야 할 곳이 많이 있습니다. 팩토리를 사용하면 변경해야 할 코드의 양이 줄어 듭니다.
정적 팩토리 메소드는 하나의 단일 인스턴스 만 사용할 구체적 클래스를 리턴하도록하려면 좋습니다.
예를 들어, 데이터베이스 연결 클래스에서 하나의 클래스 만 데이터베이스 연결을 작성하도록 할 수 있으므로 Mysql에서 Oracle로 전환하기로 결정한 경우 하나의 클래스에서 논리를 변경할 수 있으며 나머지 응용 프로그램은 새로운 연결을 사용하십시오.
데이터베이스 풀링을 구현하려는 경우 나머지 응용 프로그램에 영향을주지 않고 수행됩니다.
출고시 변경 될 수있는 나머지 응용 프로그램을 보호합니다. 이것이 목적입니다.
정적 인 이유는 제한된 리소스 (소켓 연결 또는 파일 핸들 수)를 추적하려는 경우이 클래스는 얼마나 많은 시간이 경과 및 반환되었는지 추적 할 수 있기 때문에 제한된 자원.
개인 생성자가있는 정적 팩토리 메소드의 장점 중 하나 (인스턴스가 외부에서 작성되지 않도록하기 위해 외부 클래스에 대해 오브젝트 작성이 제한되어야 함)는 인스턴스 제어 클래스를 작성할 수 있다는 것 입니다. 그리고 예를 제어 클래스는 두 개의 동일한 별개의 인스턴스 (존재하지 않는 것을 보장 a.equals (b)는 == B 전용 경우 경우 ) 프로그램 중 그 방법을 실행하는 당신이 개체의 평등을 확인하실 수 있습니다 == 대신 운영자 동등의 방법 효과적인 java에 따르면.
정적 팩토리 메소드가 반복 호출에서 동일한 오브젝트를 리턴하는 기능을 통해 클래스는 언제든지 존재하는 인스턴스를 엄격하게 제어 할 수 있습니다. 이를 수행하는 클래스는 인스턴스 제어라고합니다. 인스턴스 제어 클래스를 작성해야하는 몇 가지 이유가 있습니다. 인스턴스 제어를 통해 클래스는 단일 항목 (항목 3)이거나 인스턴스화 할 수 없음 (항목 4)임을 보장 할 수 있습니다. 또한 불변 클래스 (항목 15)는 두 개의 동일한 인스턴스가 존재하지 않음을 보장 할 수 있습니다. a. == b 인 경우에만 a.equals (b). 클래스가 이러한 보증을하는 경우, 클라이언트는 equals (Object) 메소드 대신 == 연산자를 사용하여 성능을 향상시킬 수 있습니다. 열거 형 (항목 30)은이 보증을 제공합니다.
효과적인 Java에서 Joshua Bloch (항목 1, 6 페이지)
공전
키워드 'static'으로 선언 된 멤버입니다.
공장 방법
새로운 객체를 생성하고 반환하는 메소드.
자바로
프로그래밍 언어는 '정적'의 의미와 관련이 있지만 '공장'의 정의와는 관련이 없습니다.
Java 구현에는 java.util.Arrays 및 java.util.Collections 유틸리티 클래스가 포함되어 있습니다. 둘 다 정적 팩토리 메소드 , 예제 및 사용 방법을 포함합니다.
Arrays.asList("1","2","3")
Collections.synchronizedList(..), Collections.emptyList(), Collections.unmodifiableList(...)
(일부 예제 만, javadocs에서 mor 메소드 예제를 확인할 수 있습니다 https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html )
또한 java.lang.String 클래스에는 정적 팩토리 메소드가 있습니다 .
String.format(...), String.valueOf(..), String.copyValueOf(...)