주어진 클래스의 각 인스턴스가 고유하게 식별 가능한 인스턴스인지 확인하는 다른 방법을 찾고 있습니다.
예를 들어, Name
필드 가있는 클래스가 있습니다 name
. John Smith Name
로 name
초기화 된 객체가 있으면 John Smith Name
라는 이름으로 다른 객체 를 인스턴스화 할 수 있기를 원하지 않거나 인스턴스화가 발생하면 원래 객체에 대한 참조가 오히려 다시 전달되기를 원합니다. 새로운 물체보다.
이 작업을 수행하는 한 가지 방법은 Map
현재의 모든 Name 객체 를 보유하는 정적 팩토리를 유지하는 것이며 팩토리는 John Smith를 가진 객체가 이름으로 존재하지 않는지 확인합니다. Name
목적.
내 머리 꼭대기에서 생각할 수있는 또 다른 방법은 Name
클래스에 정적 맵이 있고 전달 된 값 name
이 이미 다른 객체에서 사용중인 경우 생성자가 예외를 던지는 호출 할 때 예외가 발생 한다는 것을 알고 있습니다 생성자에서는 일반적으로 나쁜 생각 입니다.
이것을 달성하는 다른 방법이 있습니까?
답변
실제로 당신은 이미 당신의 질문에 대답했습니다. 첫 번째 방법이 더 효과적입니다. 생각하는 것 static factory
보다 항상 사용하는 것이 좋습니다 constructor
. 따라서이 Constructor
경우 사용 을 피할 수 있습니다 . 그렇지 않으면 throw some exception
지정된 이름의 인스턴스가 이미 존재하는 경우가 있습니다.
그래서, 당신은 정적 팩토리 메소드 생성 할 수 있습니다 : – getInstanceWithName(name)
그 이름으로 이미 인스턴스를 얻을 것이다, 그것은 존재하지 않는 경우, 그것은 새로운 인스턴스를 생성합니다, 당신은 할 constructor
다루는 경우가 대부분 수행해야합니다으로, 개인 static factories
.
또한 클래스 에서 정적 List
또는 Map
생성 된 모든 고유 인스턴스 를 유지해야합니다 Factory
.
편집 :-
당신은 확실히 효과적인 Java- 항목 # 1을 거쳐야합니다 : 생성자보다 정적 팩토리를 고려하십시오 . 그 책보다 더 나은 설명을 얻을 수 없습니다.
답변
효과적인 자바에 대한 언급은 많은 신뢰성을 추가하는 것으로 보이므로이 답변은 다음과 같습니다.
- 효과적인 Java 항목 8 : 동일 항목을 재정의 할 때 일반 계약 준수
- 효과적인 Java 항목 9 : equals를 재정의 할 때 항상 hashCode를 재정의하십시오.
- 효과적인 Java 항목 15 : 변경 가능성 최소화
이 이름 객체의 인스턴스가 두 개 이상인 경우 한 단계 뒤로 물러서서 왜 관심이 있는지 궁금합니다.
이런 종류의 객체 풀링을 거의 할 필요가 없습니다. OP 가이 작업을 수행하고 있기 때문에 Name
객체와 단순히 객체를 비교할 수 있습니다 ==
. 또는 키와 비슷한 Name
내부 의 객체를 사용하십시오 HashMap
.
그렇다면 이것은의 적절한 구현을equals()
통해 해결할 수있는 것입니다 .
이렇게 :
public final class Name {
private final String name;
public Name(String name) {
if (name == null) {
name = ""; //or exception if you like
}
this.name = name;
}
public String getName() {
return name;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Name)) {
return false;
}
Name other = (Name) o;
return other.name.equals(name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}
완료되면 다음이 적용됩니다.
Name a = new Name("weston");
Name b = new Name("weston");
assert(a.equals(b)); //same but:
assert(a!=b); //not the same instance
//test out the Name instances in a hashmap:
HashMap<Name,Object> map = new HashMap<Name,Object>();
Object detailsIn = new Object();
map.put(a,detailsIn);
Object detailsOut = map.get(b);
assert(detailsIn==detailsOut); //the map returned the same details object
//even though we put with `a` and got with `b` thanks to our correct equals implementation
나는 당신의 목표를 추측하고 있지만,이 방법 Name
으로 해시 맵 등에서 클래스를 사용할 수 있으며 정확히 같은 인스턴스 일 필요는 없습니다 .
답변
Name
인터페이스 만들기NameFactory
메소드를 사용 하여 인터페이스 작성Name getByName(String)
- 의 구현을 작성
NameFactory
와Map<String,WeakReference<Name>>
그 안에 synchronize
의getByName
새로운 인스턴스를 만들기 전에 메소드 내부의 이름으로 맵에Name
- 선택적으로, 구현
Name
내부 에서 인터페이스 의 정적 개인 구현을 사용 하십시오.NameFactory
이 접근 방식을 통해 다음을 보장 할 수 있습니다.
Name
언제든지 하나의 인스턴스 만 존재합니다.- 수업
Name
시간에 필요한 것보다 더 오래 붙을 때 “Lingerer”메모리 누수가 발생하지 않습니다. - 인터페이스를 사용하기 때문에 모의 객체로 디자인을 테스트 할 수 있습니다.
답변
getNameInstance(String)
같은 이름을 가진 객체가 이미 존재한다면 (예를 들어 정적 클래스의 hastable을 기반으로) 생성자를 private로 만들고 메소드 를 만들어야합니다. 해시 테이블에
답변
다음을 시도하십시오. 생성 한 각 개체를 추적해야합니다. 이를 위해 List를 사용하고 있습니다. 클래스 생성자를 비공개로 설정하여 인스턴스를 만들기 전에 사전 확인을 적용 할 수 있습니다.
class UniqueName
{
private string Name;
public int ID;
private static int Count=0;
static List<UniqueName> lt=new List<UniqueName>();
private UniqueName(string Name)
{
this.Name = Name;
ID = ++Count;
}
public static UniqueName GetUniqueueInstance(string Name)
{
foreach (UniqueName un in lt)
{
if ( string.Compare( un.Name,Name,StringComparison.InvariantCultureIgnoreCase)==0)
return un;
}
UniqueName temp=new UniqueName(Name);
lt.Add(temp);
return temp;
}
}