복붙노트

[SCALA] 긴 매개 변수 목록을 가진 생성자를 사용하지 않고 큰, 불변의 객체를 구축

SCALA

긴 매개 변수 목록을 가진 생성자를 사용하지 않고 큰, 불변의 객체를 구축

좀 큰 (3 개 이상의 필드)이 깡통을 객체와 불변해야합니다. 내가 그 경우에 실행할 때마다 나는 긴 매개 변수 목록과 생성자 가증를 생성하는 경향이있다.

사용하기 어려운, 잘 느끼고, 가독성 겪고있다하지 않습니다.

필드가 목록 같은 집합 형의 어떤 종류의 경우는 더욱 심각하다. 간단한의 addSibling는 (S S) 너무 오브젝트 생성을 용이하게하지만, 오브젝트 렌더링을 변경할 것이다.

너희들은 이런 경우에 무엇을 사용합니까?

나는 스칼라와 자바,하지만 난 문제가 긴 언어는 객체 지향만큼 언어 무신론자라고 생각합니다.

내가 생각할 수있는 솔루션 :

해결법

  1. ==============================

    1.글쎄, 당신은 생성하면 모두 더 쉽게 읽고 불변의 객체 싶어?

    글쎄, 당신은 생성하면 모두 더 쉽게 읽고 불변의 객체 싶어?

    나는 제대로 유창 인터페이스를 사용하면 도움이 될 것 같아요.

    그것은이 (순수하게 만들어 예)과 같을 것이다 :

    final Foo immutable = FooFactory.create()
        .whereRangeConstraintsAre(100,300)
        .withColor(Color.BLUE)
        .withArea(234)
        .withInterspacing(12)
        .build();
    

    대부분의 자바 프로그래머가 유창 인터페이스 오해 물론 완전히 잘못이다 오브젝트를 구축하는 데 필요한 방법, 자신의 객체를 오염 때문에 굵은 글씨로 "제대로"썼다.

    트릭은 빌드 () 메소드는 실제로 푸 (따라서 당신이 푸 불변 일 수있다)을 생성한다는 것입니다.

    FooFactory.create (), whereXXX (..)와 withXXX (..) 모두가 "뭔가"를 만들 수 있습니다.

    다른 그 무언가가 .... 여기 한 가지 방법이다하는 FooFactory 될 수있다

    당신 FooFactory는 다음과 같이 보일 것이다 :

    // Notice the private FooFactory constructor
    private FooFactory() {
    }
    
    public static FooFactory create() {
        return new FooFactory();
    }
    
    public FooFactory withColor( final Color col ) {
        this.color = color;
        return this;
    }
    
    public Foo build() {
        return new FooImpl( color, and, all, the, other, parameters, go, here );
    }
    
  2. ==============================

    2.스칼라 2.8, 당신은 이름을 지정하고 기본 매개 변수뿐만 아니라 경우 클래스에 복사 방법을 사용할 수 있습니다. 여기에 몇 가지 예제 코드는 다음과 같습니다

    스칼라 2.8, 당신은 이름을 지정하고 기본 매개 변수뿐만 아니라 경우 클래스에 복사 방법을 사용할 수 있습니다. 여기에 몇 가지 예제 코드는 다음과 같습니다

    case class Person(name: String, age: Int, children: List[Person] = List()) {
      def addChild(p: Person) = copy(children = p :: this.children)
    }
    
    val parent = Person(name = "Bob", age = 55)
      .addChild(Person("Lisa", 23))
      .addChild(Person("Peter", 16))
    
  3. ==============================

    3.음, 스칼라 2.8에이 사항을 고려하십시오

    음, 스칼라 2.8에이 사항을 고려하십시오

    case class Person(name: String, 
                      married: Boolean = false, 
                      espouse: Option[String] = None, 
                      children: Set[String] = Set.empty) {
      def marriedTo(whom: String) = this.copy(married = true, espouse = Some(whom))
      def addChild(whom: String) = this.copy(children = children + whom)
    }
    
    scala> Person("Joseph").marriedTo("Mary").addChild("Jesus")
    res1: Person = Person(Joseph,true,Some(Mary),Set(Jesus))
    

    이것은 물론, 문제의 점유율을 가지고있다. 예를 들어, 신봉 및 옵션 [사람]을 제작 한 다음 서로 결혼 한 두 사람을 얻는보십시오. 나는 개인 VAR 및 / 또는 개인 생성자 플러스 공장 하나에 의지하지 않고 그것을 해결하는 방법을 생각할 수 없다.

  4. ==============================

    4.여기에 더 많은 옵션이 몇 가지 있습니다 :

    여기에 더 많은 옵션이 몇 가지 있습니다 :

    구현 자체는 변경 가능합니다, 그러나 가변 및 불변에 노출하는 인터페이스를 분리한다. 이것은 스윙 라이브러리 디자인에서 가져옵니다.

    public interface Foo {
      X getX();
      Y getY();
    }
    
    public interface MutableFoo extends Foo {
      void setX(X x);
      void setY(Y y);
    }
    
    public class FooImpl implements MutableFoo {...}
    
    public SomeClassThatUsesFoo {
      public Foo makeFoo(...) {
        MutableFoo ret = new MutableFoo...
        ret.setX(...);
        ret.setY(...);
        return ret; // As Foo, not MutableFoo
      }
    }
    

    응용 프로그램이 불변의 객체 (예를 들어, 구성 객체)의 큰하지만 정의 사전 설정이 포함되어있는 경우, 당신은 스프링 프레임 워크를 사용하는 것이 좋습니다.

  5. ==============================

    5.그것은 불변의 종류가 기억하는 데 도움이됩니다. 귀하의 경우, 나는 "아이스"불변성 정말 잘 작동합니다 생각 :

    그것은 불변의 종류가 기억하는 데 도움이됩니다. 귀하의 경우, 나는 "아이스"불변성 정말 잘 작동합니다 생각 :

    당신이 당신의 개체를 초기화 그래서, 다음은 더 이상 쓸 수 있음을 나타내는 일종의 "동결"플래그를 설정합니다. 함수가 여전히 API를 소비하는 고객에게 순수하므로 바람직하게, 당신은 함수 뒤에 돌연변이를 숨길 것입니다.

  6. ==============================

    6.또한 불변의 객체 메소드를 노출 할 그 (addSibling 등) 뮤 테이터처럼 보이지만 그들에게 새로운 인스턴스를 반환 할 수 있습니다. 즉, 불변 스칼라 컬렉션이하는 일입니다.

    또한 불변의 객체 메소드를 노출 할 그 (addSibling 등) 뮤 테이터처럼 보이지만 그들에게 새로운 인스턴스를 반환 할 수 있습니다. 즉, 불변 스칼라 컬렉션이하는 일입니다.

    단점은 당신이 필요 이상으로 인스턴스를 만들 수 있다는 것입니다. 당신이 부분적으로 내장 된 객체를 처리 할 수없는 경우가 아니라면 (대부분의 경우에 괜찮 형제 자매가없는 일부 노드와 같은) 중간 유효한 구성이 존재하는 경우 그것은 또한에만 적용 할 수 있습니다.

    예를 들어, 아직 목적지가없는 그래프 에지 유효한 그래프 에지 아니다.

  7. ==============================

    7.네 가지 가능성을 고려 :

    네 가지 가능성을 고려 :

    new Immutable(one, fish, two, fish, red, fish, blue, fish); /*1 */
    
    params = new ImmutableParameters(); /*2 */
    params.setType("fowl");
    new Immutable(params);
    
    factory = new ImmutableFactory(); /*3 */
    factory.setType("fish");
    factory.getInstance();
    
    Immutable boringImmutable = new Immutable(); /* 4 */
    Immutable lessBoring = boringImmutable.setType("vegetable");
    

    나, 2, 3의 각각에 4 차의 상황에 적합하다. 첫 번째는 OP에 의해 인용 된 이유, 사랑에 어렵고, 일반적으로 약간의 크리프 고통과 리팩토링을 필요로 한 디자인의 증상입니다.

    상태가있는 경우 (3) 선택의 디자인 인 반면의 '공장'뒤에 어떤 상태가 없을 때 내가 (2)로 나열하고있어 좋다. 내가 스레드와 동기화에 대한 걱정을하지 않을 경우 자신이 오히려 (3)보다 (2)를 사용하여 찾을 수 있습니다, 나는 많은 개체의 생산을 통해 비싼 설정을 상각에 대해 걱정할 필요가 없습니다. (3) 실제 작업은 공장의 건설에 갈 때 다른 한편으로는, (등, 구성 파일을 읽기는 SPI에서 설정) 등이라고합니다.

    당신이 작은 불변의 객체를 많이 가지고 바람직한 패턴이 낡은 뉴스 것들을 얻을 여기서 마지막으로, 다른 사람의 대답은, 옵션 (4)을 언급했다.

    나는 '패턴 팬 클럽'의 회원이 아니에요 주 - 물론, 몇 가지 가치를 에뮬레이션하지만, 사람들이 그들에게 이름과 재미 모자를 제공하면 그들은 자신의 도움이되지 않는 삶에 걸릴 나에게 보인다.

  8. ==============================

    8.또 다른 잠재적 인 옵션은 적은 수의 구성 필드를 가지고 리팩토링이다. 서로에서만 작동합니다 (대부분) 필드의 그룹은, 자신의 작은 불변의 객체로를 수집합니다. 이 "큰"개체의 생성자 / 빌더 바와 같이 그 "작은"개체의 생성자 / 빌더는 더 관리해야한다.

    또 다른 잠재적 인 옵션은 적은 수의 구성 필드를 가지고 리팩토링이다. 서로에서만 작동합니다 (대부분) 필드의 그룹은, 자신의 작은 불변의 객체로를 수집합니다. 이 "큰"개체의 생성자 / 빌더 바와 같이 그 "작은"개체의 생성자 / 빌더는 더 관리해야한다.

  9. ==============================

    9.나는 C #을 사용하고, 이러한 나의 접근 방식이다. 치다:

    나는 C #을 사용하고, 이러한 나의 접근 방식이다. 치다:

    class Foo
    {
        // private fields only to be written inside a constructor
        private readonly int i;
        private readonly string s;
        private readonly Bar b;
    
        // public getter properties
        public int I { get { return i; } }
        // etc.
    }
    

    선택적 매개 변수와 옵션 1. 생성자

    public Foo(int i = 0, string s = "bla", Bar b = null)
    {
        this.i = i;
        this.s = s;
        this.b = b;
    }
    

    예를 들어,로 사용 새로운 푸 (5, B : 새로운 바 (무엇이든)). 아니 4.0 전에 Java 또는 C # 버전. 하지만 여전히 가치를 보여주는, 모든 솔루션은 언어 무신론자 얼마나되지 예제가있다.

    단일 매개 변수 객체를 복용 옵션 2. 생성자

    public Foo(FooParameters parameters)
    {
        this.i = parameters.I;
        // etc.
    }
    
    class FooParameters
    {
        // public properties with automatically generated private backing fields
        public int I { get; set; }
        public string S { get; set; }
        public Bar B { get; set; }
    
        // All properties are public, so we don't need a full constructor.
        // For convenience, you could include some commonly used initialization
        // patterns as additional constructors.
        public FooParameters() { }
    }
    

    사용 예 :

    FooParameters fp = new FooParameters();
    fp.I = 5;
    fp.S = "bla";
    fp.B = new Bar();
    Foo f = new Foo(fp);`
    

    3.0 C에서의 # 구문 (이전의 예와 동등한 의미) 이니셜 오브젝트이 더 우아한한다 :

    FooParameters fp = new FooParameters { I = 5, S = "bla", B = new Bar() };
    Foo f = new Foo(fp);
    

    옵션 3 : 매개 변수와 같은 거대한 번호가 필요하지 클래스를 재 설계. 여러 클래스로의 repsonsibilities를 분할 할 수있다. 또는 필요에 따라,하지 생성자에 있지만 특정 메서드에 매개 변수를 전달합니다. 이 때 항상 실행 가능하지,하지만, 그것의 가치는 일.

  10. from https://stackoverflow.com/questions/2848938/building-big-immutable-objects-without-using-constructors-having-long-parameter by cc-by-sa and MIT license