2023. 3. 2. 15:54ใJAVA/Effective JAVA
[์ดํํฐ๋ธ ์๋ฐ] 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์ ์๋ฌด๋ฐ ๊ฒฐํจ์ด ์๋๊ฐ? ๋ง์ฝ ๊ฒฐํจ์ด ์๋ค๋ฉด ์ด ๊ฒฐํจ์ด ํ์ ํด๋์ค๋ก ์ ํ๋ผ๋ ๊ด์ฐฎ์๊ฐ? ... ์ ๋ํด์ ์๊ฐํด๋ด์ผ ํ๋ค.
์์์ ์ทจ์ฝ์ ์ ํผํ๋ ค๋ฉด ์์ ๋์ ์ ์ปดํฌ์ง์ ๊ณผ ์ ๋ฌ์ ์ฌ์ฉํ์!!