문제

나는 자바 콩에 불변성을 제공 할 가능성에 대해 매우 궁금합니다 (여기서 콩은 멤버에게 게터와 세터를 제공하는 빈 생성자가있는 클래스를 의미합니다). 분명히 이러한 클래스는 불변이 아니며 데이터 계층에서 값을 전송하는 데 사용되는 곳은 실제 문제처럼 보입니다.

이 문제에 대한 한 가지 접근법은 여기에서 "C#의 불변 객체 패턴"이라는 StackoverFlow에서 언급되어 있는데, 여기서 객체가 완전히 만들어진 경우 냉동됩니다. 나는 대안적인 접근 방식을 가지고 있으며 사람들의 의견을 듣고 싶습니다.

이 패턴에는 돌연변이가없고 불변성이없는 두 가지 클래스가 불변성과 변이성이 포함되어 있지 않습니다.

예를 들어

public interface DateBean {
    public Date getDate();
    public DateBean getImmutableInstance();
    public DateBean getMutableInstance();
}

public class ImmutableDate implements DateBean {
    private Date date;

ImmutableDate(Date date) {
    this.date = new Date(date.getTime());
}

public Date getDate() {
    return new Date(date.getTime());
}

    public DateBean getImmutableInstance() {
        return this;
    }

    public DateBean getMutableInstance() {
        MutableDate dateBean = new MutableDate();
        dateBean.setDate(getDate());
        return dateBean;
    }
}

public class MutableDate implements DateBean {
    private Date date;

public Date getDate() {
    return date;
}

public void setDate(Date date) {
    this.date = date;
}

public DateBean getImmutableInstance() {
    return new ImmutableDate(this.date);
}

    public DateBean getMutableInstance() {
        MutableDate dateBean = new MutableDate();
        dateBean.setDate(getDate());
        return dateBean;
    }
}

이 접근법을 사용하면 (일반적인 규칙에 의해) 반사를 사용하여 Bean을 구성 할 수 있으며 가장 가까운 기회에서 불변 변형으로 변환 할 수 있습니다. 불행히도 콩 당 많은 양의 보일러 플레이트가 있습니다.

이 문제에 대한 다른 사람들의 접근 방식을 듣고 싶습니다. (좋은 질문을하지 않는 것에 대한 나의 사과, 논의보다는 대답 할 수 있습니다 :)

도움이 되었습니까?

해결책

대표단 패턴을 사용할 것 같아요 - 생성자에 지정되어야하는 단일 데이트 멤버와 함께 불변형 클래스를 만드십시오.

public class ImmutableDate implements DateBean
{
   private DateBean delegate;

   public ImmutableDate(DateBean d)
   {
      this.delegate = d;
   }

   public Date getDate()
   {
      return delegate.getDate();
   }
}

데이트 빙 D에서 불변성을 강요해야한다면, 나는 새로운 불변성 (d)에 불과합니다. 나는 똑똑했고 대의원을 위임하지 않았는지 확인했지만 아이디어를 얻었습니다. 이는 고객이 변이 할 수있는 것으로 캐스팅하려는 문제를 피합니다. 이것은 jdk가 collections.unmodifiablemap () 등으로하는 것과 매우 흡사합니다. (이 경우, 돌연변이 함수는 여전히 구현되어야하며, 런타임 예외를 던지도록 코딩되어 있습니다. 돌연변이터).

그러나 다시 그것은 지루한 보일러 플레이트 코드이지만 Eclipse와 같은 좋은 IDE가 몇 번의 마우스 클릭만으로 자동 생성 할 수있는 일종의 것입니다.

그것이 당신이 많은 도메인 객체를 수행하게되는 일이라면, 동적 프록시 또는 AOP를 사용하는 것을 고려할 수 있습니다. 그런 다음 모든 객체에 대한 프록시를 구축하고 모든 GET 메소드를 위임하고 세트 방법을 적절하게 갇히거나 무시하는 것이 비교적 쉽습니다.

다른 팁

일부 의견 (반드시 문제가 필요하지는 않음) :

  1. 날짜 클래스는 자체가 변하지 않으므로 불변성을 보호하기 위해 올바르게 복사하고 있지만 개인적으로 나는 생성자의 Long으로 전환하고 Getter에서 새 날짜 (LongValue)를 반환하는 것을 선호합니다.
  2. 두 가지 getWhateWinstance () 메소드는 캐스팅이 필요할 때 DateBean을 반환합니다. 대신 특정 유형을 반환하기 위해 인터페이스를 변경하는 것이 아이디어 일 수 있습니다.
  3. 내가 두 개의 클래스를 돌연변이 할 수 있고 불변의 하나의 불변을 가질 경향이 있다고 말하면서, 적절한 경우 공통 (예 : get het) 인터페이스를 공유합니다. 앞뒤로 많은 변환이있을 것이라고 생각되면 두 클래스에 사본 생성자를 추가하십시오.
  4. 필드를 선언하기 위해 불변의 수업을 선호합니다 결정적인 컴파일러가 불변성을 시행하도록합니다.

예를 들어

public interface DateBean {
    public Date getDate();
}

public class ImmutableDate implements DateBean {
    private final long date;

    ImmutableDate(long date) {
       this.date = date;
    }

    ImmutableDate(Date date) {
       this(date.getTime());
    }

    ImmutableDate(DateBean bean) {
       this(bean.getDate());
    }

    public Date getDate() {
         return new Date(date);
    }
}


public class MutableDate implements DateBean {
    private long date;

    MutableDate() {}

    MutableDate(long date) {
       this.date = date;
    }

    MutableDate(Date date) {
       this(date.getTime());
    }

    MutableDate(DateBean bean) {
       this(bean.getDate());
    }

    public Date getDate() {
        return new Date(date);
    }

    public void setDate(Date date) {
        this.date = date.getTime();
    }

}

나는 콩의 돌연변이를 제어하기 위해 인터페이스와 캐스팅을 사용합니다. 나는 내 도메인 객체를 다음과 같은 방법으로 복잡하게 할 좋은 이유가 없다. getImmutableInstance() 그리고 getMutableInstance().

왜 상속과 추상화를 사용하지 않습니까? 예를 들어

public interface User{

  long getId();

  String getName();

  int getAge();

}

public interface MutableUser extends User{

  void setName(String name);

  void setAge(int age);

}

코드의 클라이언트가 수행 할 작업은 다음과 같습니다.

public void validateUser(User user){
  if(user.getName() == null) ...
}

public void updateUserAge(MutableUser user, int age){
  user.setAge(age);
}

당신의 질문에 대답합니까?

YC

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top