{"componentChunkName":"component---src-templates-post-template-jsx","path":"/history/posts/2020-10-04--003--01","result":{"data":{"site":{"siteMetadata":{"title":"Blog by Eunyoung","subtitle":"작업 기록 블로그","copyright":"© All rights reserved.","author":{"name":"EunYoung","twitter":"#"},"disqusShortname":"","url":"https://ssongey.github.io"}},"markdownRemark":{"id":"ee76f05b-68f3-52c5-8958-c600a69d60a7","html":"<h2>아이템1) 생성자 대신 정적 팩터리 메서드를 고려해라</h2>\n<p>정적 팩터리 메서드와 public 생성자는 각자의 쓰임새가 있으니 상대적인 장단점을 이해하고 사용하는 것이 좋다.\n그렇다고 하더라고 정적 팩터리를 사용하는 게 유리한 경우가 더 많으므로 무작정 public 생성자를 제공하던 습관이 있다면 고치자.</p>\n<h3>정적 팩터리 메서드가 생성자보다 좋은 장점</h3>\n<h4>1. 이름을 가질 수 있다.</h4>\n<ul>\n<li>\n<p>어떤 역할의 객체 생성인지 명시 가능</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">값이 소스인 BigInteger를 반환  \n생성자 :            BigInteger(int, int, Random)\n정적 팩터리 매서드 : BigInteger.probablePrime(int, Random)</code></pre></div>\n</li>\n</ul>\n<h4>2. 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.</h4>\n<ul>\n<li><a href=\"/devHistoryBlog/history/posts/2020-10-04--004\">플라이웨이트 패턴(Flyweight pattern)</a><br>\n데이터를 공유하여 메모리를 절약하는 패턴,\n공통으로 사용되는 객체는 한번만 사용되고 Pool에의해서 관리, 사용된다.\n(JVM의 String Pool에서 같은 String이 잇는지 먼저 찾는다. [불변객체 String])  </li>\n<li>불변클래스<br>\n인스턴스를 미리 만들어 놓거나 인스턴스 캐싱으로 재사용하여 불필요한 객체 생성을 피할 수 있다.\nex ) Boolean.valueOf(boolean b);</li>\n<li>인스턴스 통제(instance-controlled) 클래스<br>\n정적 팩터리 방식의 클래스는 언제 어느 인스턴스를 살아 있게 할지를 철저히 통제할 수 있다.<br>\n싱글턴 / noninstatntialbe로 만들 수 있다.<br>\n불변 값 클래스에서 동치 인스턴스 하나임을 보장 ex ) Enum : 인스턴스가 하나만 만들어짐</li>\n</ul>\n<h4>3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.</h4>\n<ul>\n<li>생성자의 경우에는 반환형 클래스가 정해져있지만, static factory method 는 하위타입을 반환할수도 있다. </li>\n<li>java.util.Collections 가 예시다</li>\n</ul>\n<h5>ps. Java8 인터페이스</h5>\n<ul>\n<li>Default Method<br>\n— default 키워드를 통해 메서드를 구현할 수 있다.<br>\n또, 이를 구현하는 클래스는interface의 메서드를 @Override 할 수 있다.</li>\n</ul>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">interface</span> <span class=\"token class-name\">Coffee</span> <span class=\"token punctuation\">{</span>  \n  <span class=\"token keyword\">default</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getBrandName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token string\">\"MEGA\"</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token comment\">// getBrandName이 없는 DTO 클래스 생성</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Americano</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">Coffee</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">long</span> price<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">public</span> <span class=\"token class-name\">Americano</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">long</span> price<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>price <span class=\"token operator\">=</span> price<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token comment\">// default 메소드에 적용되어있는 getBrandName() 메소드 사용</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Test</span> <span class=\"token punctuation\">{</span>    \n  <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">void</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> args<span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">Coffee</span> coffee <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Americano</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">System</span><span class=\"token punctuation\">.</span>out<span class=\"token punctuation\">.</span><span class=\"token function\">println</span><span class=\"token punctuation\">(</span>coffee<span class=\"token punctuation\">.</span><span class=\"token function\">getBrandName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<ul>\n<li>디폴트 메소드 vs 추상클래스 차이점<br>\n— 인터페이스는 private 값을 가지지 못한다.(오직 public, abstract, default, static 상태만 가질 수 있다.)\n— 인터페이스는 생성자를 가질 수 없지만 추상클래스는 생성자를 가질 수 있다.</li>\n</ul>\n<p>참고 - 인터페이스에 대한 설명<br>\n<a href=\"https://wedul.site/320\">https://wedul.site/320</a><br>\n<a href=\"https://m.blog.naver.com/heartflow89/220969525191\">https://m.blog.naver.com/heartflow89/220969525191</a></p>\n<h4>4. 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.</h4>\n<ul>\n<li>하위타입이기만 하면 어떤 클래스의 객체를 반환하든 상관없다.<br>\n— EX) EnumSet<br>\n— 정적 팩터리 메소드인 noneOf() 에서,<br>\n원소가 64개 이하면 long 변수 하나로 관리하는 RegularEnumSet 을 반환하고,<br>\n65개 이상이면 long 배열로 관리하는 JumboEnumSet 을 반환\n— 클라이언트에서는 이 두 객체의 존재를 모르고, 다음 릴리즈에서 이 내용을 변경할 수 있는 유연성을 가진다.\n\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/2b4904268c2b2accb90da2f63ccfdb66/68de2/003--01-1.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 677px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 72.5%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAABJ0AAASdAHeZh94AAABn0lEQVQ4y41TUXaDMAzjOCO2kzihtLC93f9WnpwE2m7d3j6EgRBhycqUhWxNZO8FNZPVWu12u1lBXS5rq5dlaffrdbOU1SgEEyZj5hNEZAHvJxI8gHQOwBwG5l8RsB5C3/wdTjr5hSObqJgk7sj466ipRotYOyBZ2kYaBI8ITuit5+QQyMkmEQQxWRoQ/IzwzRPoJ84OnVAlmGKjarWYkuWopqk0CPFLea/kDg+pyQvsLftCaPXAU1c+CLl3et4/dhgOD+ENR2q+iQ4PT9+67OZj6T4e916d+ElygYcKD7UslrV0/yRb5IgP539JvhPi4lnsHqqlFIGMIRUAQ2LpkPhUmUYORTq4e40OAwhDG0yRN1N+Q5dquaBTDEhjgQJHbah5acPyPVWz1Rb+BapiJ4wI9gVZ21cs4kQkTFoLNi4rTo1bkNsGf+ex8uq2eLxml+phH7acwXbSvbJtILwuO7BZhZ/rbbP949O2bbeCrl2WE8mQ+CqLE7UFtsyexYgMQqqktphxbpucFP/M3iPpdBxub7/jPtXz/PrzH6fjEV+wDar6BnR1hgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"003  01 1\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/2b4904268c2b2accb90da2f63ccfdb66/68de2/003--01-1.png\"\n        srcset=\"/devHistoryBlog/static/2b4904268c2b2accb90da2f63ccfdb66/8ff5a/003--01-1.png 240w,\n/devHistoryBlog/static/2b4904268c2b2accb90da2f63ccfdb66/e85cb/003--01-1.png 480w,\n/devHistoryBlog/static/2b4904268c2b2accb90da2f63ccfdb66/68de2/003--01-1.png 677w\"\n        sizes=\"(max-width: 677px) 100vw, 677px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </li>\n</ul>\n<p>\n  <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/devHistoryBlog/static/5af9e2a6eff94c8f4abfe68c2a9c3d0e/0ad97/003--01-2.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n  \n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 717px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 37.083333333333336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABJ0AAASdAHeZh94AAABAElEQVQoz22RSXLFIAxEfR0DAsRkO5X7X6vTAr6TRRZdjPX0BId3DlECnvvGuL/QBsfrQi8ZrXWU2mZaH6hc19aQYoT3Ht7t2DyEOR7Or41E6KgZXSOqZlzdQBWqBaXUF5y5FhFIDDMxC2IUOIpZDr+BwgqJB2abYuIlJlnyAkjckWXkHa08Au+Haed+DQOTk+AZDaMpHrZ3399sn61fD3LOr2XiPLHInLOgO5fZ7NQMnVvAmjxUTqTAsBVlu1mVMJ2jljrbNYgVsD2hncH8hhn0MF2LcFGiQRnaltrfN5zvSCMtG7j3TOQD/PzFBNoP2cE549d4nv/G/Tl7YR9L5gd+1NdOv215QAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"003  01 2\"\n        title=\"\"\n        src=\"/devHistoryBlog/static/5af9e2a6eff94c8f4abfe68c2a9c3d0e/0ad97/003--01-2.png\"\n        srcset=\"/devHistoryBlog/static/5af9e2a6eff94c8f4abfe68c2a9c3d0e/8ff5a/003--01-2.png 240w,\n/devHistoryBlog/static/5af9e2a6eff94c8f4abfe68c2a9c3d0e/e85cb/003--01-2.png 480w,\n/devHistoryBlog/static/5af9e2a6eff94c8f4abfe68c2a9c3d0e/0ad97/003--01-2.png 717w\"\n        sizes=\"(max-width: 717px) 100vw, 717px\"\n      />\n    </span>\n  </span>\n  \n  </a>\n    </p>\n<h4>5. 정적 팩터리 메스드를 작성하는 시점에서는 반환할 객체의 클래스가 존재하지 않아도 된다.</h4>\n<p>— 다시</p>\n<h3>단점</h3>\n<ul>\n<li>정적 팩터리 메서드만 제공하는 클래스는 상속할 수 없다.<br>\n상속을 하려면 pubilc 이나 protected 생성자가 필요하기 때문이다.</li>\n<li>정적 팩터리 메서드는 프로그래머가 찾기 어렵다.\n생성자처럼 API 설명에 명확히 드러나지 않기 때문에 프로그래머가 직접 정적 팩터리 메서드를 찾아야 한다.</li>\n</ul>\n<h3>정적 팩터리 매서드 명명 방식</h3>\n<ul>\n<li>\n<p>from<br>\n— 매개변수를 하나 받아서 해당 타입의 인스턴스를 반환하는 형변환 매서드</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">Date</span> d <span class=\"token operator\">=</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">.</span><span class=\"token function\">from</span><span class=\"token punctuation\">(</span>instance<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n</li>\n<li>\n<p>of<br>\n— 여러 매개변수를 받아 적합한 타입으 ㅣ인스턴스를 반환하는 집계 메서드</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">Set</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Rank</span><span class=\"token punctuation\">></span></span> faceCards <span class=\"token operator\">=</span> <span class=\"token class-name\">EnumSet</span><span class=\"token punctuation\">.</span><span class=\"token function\">of</span><span class=\"token punctuation\">(</span>JACK<span class=\"token punctuation\">,</span> QUEEN<span class=\"token punctuation\">,</span> KING<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n</li>\n<li>\n<p>valueOf<br>\n— from과 of의 더 자세한 버전</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">BigInteger</span> prime <span class=\"token operator\">=</span> <span class=\"token class-name\">BigInteger</span><span class=\"token punctuation\">.</span><span class=\"token function\">valueOf</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">Integer</span><span class=\"token punctuation\">.</span>MAX_VALUE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n</li>\n<li>\n<p>instance 혹은 getInstance<br>\n— 매개변수를 받는다면, 매개변수로 명시한 인스턴스를 반환하지만, 같은 인스턴스임을 보장하지 않음</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">StackWalker</span> luke <span class=\"token operator\">=</span> <span class=\"token class-name\">StackWalker</span><span class=\"token punctuation\">.</span><span class=\"token function\">getInstance</span><span class=\"token punctuation\">(</span>options<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n</li>\n<li>\n<p>create 혹은 newInstance<br>\n— instance 혹은 getInstance 와 같지만, 매번 새로운 인스턴스를 생성해 반환함을 보장한다.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">Object</span> newArray <span class=\"token operator\">=</span> <span class=\"token class-name\">Array</span><span class=\"token punctuation\">.</span><span class=\"token function\">newInstance</span><span class=\"token punctuation\">(</span>classObject<span class=\"token punctuation\">,</span> arrayLen<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n</li>\n<li>\n<p>getType<br>\n— getInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩터리 매서드를 정의할 때 사용</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">FileStore</span> fs <span class=\"token operator\">=</span> <span class=\"token class-name\">Files</span><span class=\"token punctuation\">.</span><span class=\"token function\">getFileStore</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n</li>\n<li>\n<p>newType<br>\n— newInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩터리 매서트를 정의할 때 사용</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">BufferedReader</span> br <span class=\"token operator\">=</span> <span class=\"token class-name\">Files</span><span class=\"token punctuation\">.</span><span class=\"token function\">newBufferedReader</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n</li>\n<li>\n<p>type<br>\n— getType과 newType의 간결한 버전</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Complaint</span><span class=\"token punctuation\">></span></span> litany <span class=\"token operator\">=</span> <span class=\"token class-name\">Collections</span><span class=\"token punctuation\">.</span><span class=\"token function\">list</span><span class=\"token punctuation\">(</span>legacyLitany<span class=\"token punctuation\">)</span></code></pre></div>\n</li>\n</ul>","fields":{"tagSlugs":["/tags/책리뷰/","/tags/이펙티브자바/"],"slug":"/history/posts/2020-10-04--003--01"},"frontmatter":{"title":"[책리뷰/Effective Java] 객체 생성과 파괴","tags":["책리뷰","이펙티브자바"],"date":"2020-10-04","description":"아이템1) 생성자 대신 정적 팩터리 메서드를 고려해라"}}},"pageContext":{"slug":"/history/posts/2020-10-04--003--01"}},"staticQueryHashes":[]}