[์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”] Item18. ์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋ผ.

2023. 3. 2. 15:54ใ†JAVA/Effective JAVA

728x90

 

[์ดํŽ™ํ‹ฐ๋ธŒ ์ž๋ฐ”] Item18. ์ƒ์†๋ณด๋‹ค๋Š” ์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•˜๋ผ. 

์ƒ์†์„ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ž˜๋ชป ์ƒ์†ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. 

์ƒ์œ„ ํด๋ž˜์Šค์™€ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๋ชจ๋‘ ๊ฐ™์€ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ํ†ต์ œํ•˜๋Š” ํŒจํ‚ค์ง€ ์•ˆ์ด๋ฉด์„œ ํ™•์žฅํ•  ๋ชฉ์ ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ๊ณ , ๋ฌธ์„œํ™”๋„ ์ž˜ ๋œ ํด๋ž˜์Šค๋ผ๋ฉด ์ƒ์†๋„ ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์ด ๋œ๋‹ค. 

ํ•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ํŒจํ‚ค์ง€ ๊ฒฝ๊ณ„๋ฅผ ๋„˜์–ด์„œ ๋‹ค๋ฅธ ํŒจํ‚ค์ง€์˜ ๊ตฌ์ฒดํด๋ž˜์Šค๋กœ ์ƒ์†ํ•˜๋Š” ์ผ์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์œ„ํ—˜์ด ์กด์žฌํ•œ๋‹ค!!

 

 

๐Ÿ‘พ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๊ณผ ๋‹ฌ๋ฆฌ ์ƒ์†์€ ์บก์Šํ™”๋ฅผ ๊นจํŠธ๋ฆฐ๋‹ค. 

: ์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜๋Š๋ƒ์— ๋”ฐ๋ผ์„œ ํ•˜์œ„ ํด๋ž˜์Šค์˜ ๋™์ž‘์— ์ด์ƒ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. 

์ƒ์œ„ ํด๋ž˜์Šค๊ฐ€ ๋ฆด๋ฆฌ์ฆˆ๋งˆ๋‹ค ๋‚ด๋ถ€ ๊ตฌํ˜„์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ์— ๋”ฐ๋ผ์„œ ์ƒ์†์„ ๋ฐ›์€ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ ์˜ค๋™์ž‘ ํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

์ƒ์œ„ ํด๋ž˜์Šค ์„ค๊ณ„์ž๊ฐ€ ํ™•์žฅ์„ ์ถฉ๋ถ„ํžˆ ๊ณ ๋ คํ•˜๊ณ  ๋ฌธ์„œํ™”๋„ ์ œ๋Œ€๋กœ ํ•ด๋‘์ง€ ์•Š์•˜๋”๋ผ๋ฉด ํ•˜์œ„ํด๋ž˜์Šค๋Š” ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๋ณ€ํ™”์— ๋งž์ถฐ์„œ ํ•ญ์ƒ ์ˆ˜์ •ํ•ด์•ผ๋งŒ ํ•œ๋‹ค.. 

public class InstrumentedHashSet<E> extends HashSet<E>
{
   // ์ถ”๊ฐ€๋œ ์›์†Œ์˜ ์ˆ˜
   private int addCount = 0;
   
   public InstrumentedHashSet()
   {
   
   }
   
   public InstrumentedHashSet(int initCap, float loadFactor)
   {
      super(initCap, loadFactor);
   }
   
   @Override
   public boolean add(E e)
   {
      addCount++;
      return super.add(e);
   }
   
   @Override
   public boolean addAll(Collection<? extends E> c)
   {
      addCount += c.size();
      return super.addAll(c);
   }
   
   public int getAddCount()
   {
      return addCount;
   }
   
   public static void main(String[] args)
   {
      InstrumentedHashSet<String> s = new InstrumentedHashSet<>();
      s.addAll(List.of("ํ‹ฑ", "ํƒํƒ", "ํŽ‘"));
      System.out.println("s.getAddCount() = " + s.getAddCount());
   }
}

InstrumentHashSet์€ HashSet์„ ์‚ฌ์šฉํ•œ๋Š๋ฐ ์—ฌ๊ธฐ์„œ HashSet์ด ์ฒ˜์Œ ์ƒ์„ฑ๋œ ์ดํ›„์— ์›์†Œ๊ฐ€ ๋ช‡ ๊ฐœ ๋”ํ•ด์กŒ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค. 

๋”ฐ๋ผ์„œ HashSet์— ์›์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ธ add์™€ addAll์„ ์žฌ์ •์˜ํ–ˆ๋‹ค. 

 

main์—์„œ ์ด์ œ List of ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ด์„œ ์›์†Œ 3๊ฐœ๋ฅผ ๋”ํ–ˆ๋‹ค๊ณ  ํ•˜๋ฉด getAddCount์˜ ๊ฐ’์œผ๋กœ 3์„ ์˜ˆ์ธกํ•  ๊ฒƒ์ด๋‹ค.

์ •์ƒ์ ์œผ๋กœ 3์ด ์ถœ๋ ฅ๋  ๊ฒƒ์ด๋ผ๊ณ  ์˜ˆ์ƒํ–ˆ์ง€๋งŒ ๊ฒฐ๊ณผ๋Š” 6์ด ๋‚˜์˜จ๋‹ค. 

์™œ๋ƒํ•˜๋ฉด HashSet์˜ addAll ๋ฉ”์„œ๋“œ๊ฐ€ add ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค..!

์—ฌ๊ธฐ์„œ addAll ๋ฉ”์„œ๋“œ๊ฐ€ add ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ์ถ”๊ฐ€ํ•˜๋Š”๋ฐ, ์ด๋•Œ add๋Š” InstrumentHashSet์—์„œ ์žฌ์ •์˜ํ•œ ๋ฉ”์„œ๋“œ์ธ add๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ๋œ๋‹ค. 

๋”ฐ๋ผ์„œ addCount ๊ฐ’์ด ์ค‘๋ณตํ•ด์„œ ๋”ํ•ด์ ธ์„œ ๊ฒฐ๊ณผ๋กœ 6์ด ์ถœ๋ ฅ๋œ ๊ฒƒ์ด๋‹ค!

 

 

๐Ÿ’ก ๊ธฐ์กด ํด๋ž˜์Šค๋ฅผ ํ™•์žฅํ•˜๋Š” ๋Œ€์‹  ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  private ํ•„๋“œ๋กœ ๊ธฐ์กด ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๊ฒŒ ํ•˜์ž. 

: ๊ธฐ์กด ํด๋ž˜์Šค๊ฐ€ ์ƒˆ๋กœ์šด ํด๋ž˜์Šค์˜ ๊ตฌ์„ฑ์š”์†Œ๋กœ ์“ฐ์ธ๋‹ค๋Š” ๋œป์—์„œ ์ด๋Ÿฌํ•œ ์„ค๊ณ„๋ฅผ ์ปดํฌ์ง€์…˜ Composition์ด๋ผ๊ณ  ํ•œ๋‹ค. 

์ƒˆ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋“ค์€ ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๋Œ€์‘ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.  -> ์ด ๋ฐฉ์‹์„ ์ „๋‹ฌ(forwarding) ์ด๋ผ๊ณ  ํ•˜๋ฉฐ, ์ƒˆ ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋“ค์€ ์ „๋‹ฌ ๋ฉ”์„œ๋“œ (forwarding method) ๋ผ ๋ถ€๋ฅธ๋‹ค. 

 

์ปดํฌ์ง€์…˜์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์ƒˆ๋กœ์šด ํด๋ž˜์Šค๋Š” ๊ธฐ์กด ํด๋ž˜์Šค์˜ ๋‚ด๋ถ€ ๊ตฌํ˜„ ๋ฐฉ์‹์˜ ์˜ํ–ฅ์—์„œ ๋ฒ—์–ด๋‚˜๋ฉฐ, ์‹ฌ์ง€์–ด ๊ธฐ์กด ํด๋ž˜์Šค์— ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜๋”๋ผ๋„ ์ „ํ˜€ ์˜ํ–ฅ๋ฐ›์ง€ ์•Š๋Š”๋‹ค. 

public class ForwardingSet<E> implements Set<E>
{
   private final Set<E> s;
   
   public ForwardingSet(Set<E> s)
   {
      this.s = s;
   }
   
   public void clear()
   {
      s.clear();
   }
   
   public boolean contains(Object o)
   {
      return s.contains(o);
   }
   
   public boolean isEmpty()
   {
      return s.isEmpty();
   }
   
   public int size()
   {
      return s.size();
   }
   
   public Iterator<E> iterator()
   {
      return s.iterator();
   }
   
   public boolean add(E e)
   {
      return s.add(e);
   }
   
   public boolean remove(Object o)
   {
      return s.remove(o);
   }
   
   public boolean containsAll(Collection<?> collection)
   {
      return s.containsAll(collection);
   }
   
   public boolean addAll(Collection<? extends E> collection)
   {
      return s.addAll(collection);
   }
   
   public boolean removeAll(Collection<?> c)
   {
      return s.removeAll(c);
   }
   
   public boolean retainAll(Collection<?> collection)
   {
      return s.retainAll(collection);
   }
   
   public Object[] toArray()
   {
      return s.toArray();
   }
   
   public <T> T[] toArray(T[] a)
   {
      return s.toArray(a);
   }
   
   
}

 

-> ForwardingSet์€ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ „๋‹ฌ ํด๋ž˜์Šค

 

public class InstrumentedSet<E> extends ForwardingSet<E>
{
   private int addCount = 0;
   public InstrumentedSet(Set<E> s)
   {
      super(s);
   }
   
   @Override
   public boolean add(E e)
   {
      addCount++;
      return super.add(e);
   }
   
   @Override
   public boolean addAll(Collection<? extends E> collection)
   {
      addCount += collection.size();
      return super.addAll(collection);
   }
   
   public int getAddCount()
   {
      return addCount;
   }
   
   public static void main(String[] args)
   {
      InstrumentedSet<String> s = new InstrumentedSet<>(new HashSet<>());
      s.addAll(List.of("ํ‹ฑ", "ํƒํƒ", "ํŽ‘"));
      System.out.println("s.getAddCount() = " + s.getAddCount());
   }
}

 

InstrumentedSet์€ HashSet์˜ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ์ •์˜ํ•œ Set ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•ด ์„ค๊ณ„๋˜์—ˆ๋‹ค. Set ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ , Set์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” ์ƒ์„ฑ์ž๋ฅผ ํ•˜๋‚˜ ์ œ๊ณตํ–ˆ๋‹ค. ์ž„์˜์˜ Set์— ๊ณ„์ธก ๊ธฐ๋Šฅ์„ ๋ง์”Œ์›Œ ์ƒˆ๋กœ์šด Set์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ด ํด๋ž˜์Šค์˜ ํ•ต์‹ฌ์ด๋‹ค. 

 

๋‹ค๋ฅธ Set ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ์‹ธ๊ณ  (warp) ์žˆ๋‹ค๋Š” ๋œป์—์„œ InstrumentedSet ๊ฐ™์€ ํด๋ž˜์Šค๋ฅผ ๋ž˜ํผ ํฌ๋ž˜์Šค๋ผ๊ณ  ํ•˜๋ฉฐ, ๋‹ค๋ฅธ Set์— ๊ณ„์ธก ๊ธฐ๋Šฅ์„ ๋ง์”Œ์šด๋‹ค๋Š” ๋œป์—์„œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด์ด๋ผ๊ณ  ํ•œ๋‹ค. 

 

 

 

๐Ÿ“– ์ •๋ฆฌ 

์ƒ์†์€ ๋ฐ˜๋“œ์‹œ ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ์ƒ์œ„ ํด๋ž˜์Šค์˜ '์ง„์งœ' ํ•˜์œ„ ํƒ€์ž…์ธ ์ƒํ™ฉ์—์„œ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ํด๋ž˜์Šค B๊ฐ€ ํด๋ž˜์Šค A์™€ is-a ๊ด€๊ณ„์ผ ๋•Œ๋งŒ ํด๋ž˜์Šค A๋ฅผ ์ƒ์†ํ•ด์•ผ ํ•œ๋‹ค. 

์ปดํฌ์ง€์…˜์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์—์„œ ์ƒ์†์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฑด ๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋…ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋ฉฐ, ์ด๋Ÿฌํ•œ ๊ฒฐ๊ณผ๋กœ api๊ฐ€ ๋‚ด๋ถ€ ๊ตฌํ˜„์— ๋ฌถ์ด๊ณ  ๊ทธ ํด๋ž˜์Šค์˜ ์„ฑ๋Šฅ๋„ ์˜์›ํžˆ ์ œํ•œ๋˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋” ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋…ธ์ถœ๋œ ๋‚ด๋ถ€์— ์ง์ ‘ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค. 

 

์ปดํฌ์ง€์…˜ ๋Œ€์‹ ์— ์ƒ์†์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค๋ฉด ํ™•์žฅํ•˜๋ ค๋Š” ํด๋ž˜์Šค์˜ api์— ์•„๋ฌด๋Ÿฐ ๊ฒฐํ•จ์ด ์—†๋Š”๊ฐ€?  ๋งŒ์•ฝ ๊ฒฐํ•จ์ด ์žˆ๋‹ค๋ฉด ์ด ๊ฒฐํ•จ์ด ํ•˜์œ„ ํด๋ž˜์Šค๋กœ ์ „ํŒŒ๋ผ๋„ ๊ดœ์ฐฎ์€๊ฐ€? ... ์— ๋Œ€ํ•ด์„œ ์ƒ๊ฐํ•ด๋ด์•ผ ํ•œ๋‹ค. 

 

์ƒ์†์˜ ์ทจ์•ฝ์ ์„ ํ”ผํ•˜๋ ค๋ฉด ์ƒ์† ๋Œ€์‹ ์— ์ปดํฌ์ง€์…˜๊ณผ ์ „๋‹ฌ์„ ์‚ฌ์šฉํ•˜์ž!! 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90