# [Java] ์ปดํฌ์ง์ (Composition)
์ปดํฌ์ง์
: ๊ธฐ์กด ํด๋์ค๊ฐ ์๋ก์ด ํด๋์ค์ ๊ตฌ์ฑ์์๊ฐ ๋๋ ๊ฒ
์์(Inheritance)์ ๋จ์ ์ ์ปค๋ฒํ ์ ์๋ ์ปดํฌ์ง์
์ ๋ํด ์์๋ณด์
์ฐ์ ์์(Inheritance)์ด๋, ํ์ ํด๋์ค๊ฐ ์์ ํด๋์ค์ ํน์ฑ์ ์ฌ์ ์ ํ ๊ฒ์ ๋งํ๋ค. ๋ถ๋ชจ ํด๋์ค์ ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ์์์ ๋ง๊ฒ ์ฌ์ฌ์ฉํ๋ ๋ฑ, ์๋นํ ๋ง์ด ์ฐ์ด๋ ๊ฐ๋ ์ด๋ฉด์ ํ์ฉ๋๋ ๋๋ค.
ํ์ง๋ง ์ฅ์ ๋ง ์กด์ฌํ๋ ๊ฒ์ ์๋๋ค. ์์์ ์ ๋๋ก ์ฌ์ฉํ์ง ์์ผ๋ฉด ์ ์ฐ์ฑ์ ํด์น ์ ์๋ค.
# ๊ตฌํ ์์(ํด๋์คโํด๋์ค)์ ๋จ์
์บก์ํ๋ฅผ ์๋ฐ
์ ์ฐํ์ง ๋ชปํ ์ค๊ณ
๋ค์ค์์ ๋ถ๊ฐ๋ฅ
# ์ค๋ฅ์ ์์
๋ค์์, HashSet์ ์์๋ฅผ ๋ช ๋ฒ ์ฝ์ ํ๋์ง count ๋ณ์๋ก ์ฒดํฌํ์ฌ ์ถ๋ ฅํ๋ ์์ ๋ค.
public class CustomHashSet<E> extends HashSet {
private int count = 0;
public CustomHashSet(){}
public CustomHashSet(int initCap, float loadFactor){
super(initCap,loadFactor);
}
@Override
public boolean add(Object o) {
count++;
return super.add(o);
}
@Override
public boolean addAll(Collection c) {
count += c.size();
return super.addAll(c);
}
public int getCount() {
return count;
}
}
add์ addAll ๋ฉ์๋๋ฅผ ํธ์ถ ์, count ๋ณ์์ ํด๋น ํ์๋ฅผ ๋ํด์ฃผ๋ฉด์, getCount()๋ก ํธ์ถ ์๋ฅผ ์์๋ผ ์ ์๋ค.
ํ์ง๋ง, ์ค์ ๋ก ์ฌ์ฉํด๋ณด๋ฉด ์ํ๋ ๊ฐ์ ์ป์ง ๋ชปํ๋ค.
public class Main {
public static void main(String[] args) {
CustomHashSet<String> customHashSet = new CustomHashSet<>();
List<String> test = Arrays.asList("a","b","c");
customHashSet.addAll(test);
System.out.println(customHashSet.getCount()); // 6
}
}
a, b, c
์ 3๊ฐ์ง ์์๋ง ๋ฐฐ์ด์ ๋ด์ ์ ๋ฌํ์ง๋ง, ์ค์ getCount ๋ฉ์๋์์๋ 6์ด ์ถ๋ ฅ๋๋ค.
์ด๋ CustomHashSet์์ ์์์ ๋ฐ๊ณ ์๋ HashSet์ ๋ถ๋ชจ ํด๋์ค์ธ AbstractCollection
์ addAll ๋ฉ์๋์์ ํ์ธํ ์ ์๋ค.
// AbstractCollection์ addAll ๋ฉ์๋
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
}
ํด๋น ๋ฉ์๋๋ฅผ ๋ณด๋ฉด, add(e)
๊ฐ ์ฌ์ฉ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค. ์ฌ๊ธฐ์ ์ 6์ด ๋์จ์ง ์ดํด๊ฐ ๋์์ ๊ฒ์ด๋ค.
์ฐ๋ฆฌ๋ CustomHashSet์์ add()
์ addAll()
๋ฅผ ๋ชจ๋ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ count ๋ณ์๋ฅผ ๊ฐ๊ฐ ์ฆ๊ฐ์์ผ์คฌ๋ค. ๊ฒฐ๊ตญ ๋ ๋ฉ์๋๊ฐ ๋ชจ๋ ์คํ๋๋ฉด์ ์ด 6๋ฒ์ count๊ฐ ์ ์ฅ๋๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด์ ๋ ๋ฉ์๋ ์ค์ ํ๋์ count๋ฅผ ์ฆ๊ฐํ๋ ๊ณณ์ ์ง์์ผํ๋ค. ํ์ง๋ง ์ด๋ฌ๋ฉด ๋์ผ๋ก ๋ดค์ ๋ ์ฝ๋์ ๋ ผ๋ฆฌ๊ฐ ๊นจ์ง ๋ฟ๋ง ์๋๋ผ, ์ถํ์ HashSet ํด๋์ค์ ๋ณ๊ฒฝ์ด ์๊ธฐ๊ธฐ๋ผ๋ ํ๋ค๋ฉด ํฐ ์ค๋ฅ๋ฅผ ๋ฒํ ์๋ ์๊ฒ ๋๋ค.
๊ฒฐ๊ณผ๋ก ์ ์ผ๋ก, ์์ ๊ฐ์ด ์์์ ์ฌ์ฉํ์ ๋ ์ ์ฐํ์ง ๋ชปํจ๊ณผ ์บก์ํ์ ์๋ฐฐ๋ ์ ์๋ค๋ ๋ฌธ์ ์ ์ ๋ณผ ์ ์๋ค.
# ๊ทธ๋ ๋ค๋ฉด ์ปดํฌ์ง์ ์?
์์์ฒ๋ผ ๊ธฐ์กด์ ํด๋์ค๋ฅผ ํ์ฅ(extend)ํ๋ ๊ฒ์ด ์๋, ์๋ก์ด ํด๋์ค๋ฅผ ์์ฑํ์ฌ private ํ๋๋ก ๊ธฐ์กด ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ์ฐธ์กฐํ๋ ๋ฐฉ์์ด ๋ฐ๋ก ์ปดํฌ์ง์ ์ด๋ค.
forwarding์ด๋ผ๊ณ ๋ ๋ถ๋ฅธ๋ค.
์๋ก์ด ํด๋์ค์ด๊ธฐ ๋๋ฌธ์, ์ฌ๊ธฐ์ ์ด๋ ํ ์์ฑ ์์ ์ด ์ผ์ด๋๋๋ผ๋ ๊ธฐ์กด์ ํด๋์ค๋ ์ ํ ์ํฅ์ ๋ฐ์ง ์๋๋ค๋ ์ ์ด ํต์ฌ์ด๋ค.
์์ ์์ ๋ฅผ ๊ฐ์ ํ์ฌ, ์ปดํฌ์ง์ ๋ฐฉ์์ผ๋ก ๋ง๋ค์ด๋ณด์
public class CustomHashSet<E> extends ForwardingSet {
private int count = 0;
public CustomHashSet(Set<E> set){
super(set);
}
@Override
public boolean add(Object o) {
count++;
return super.add(o);
}
@Override
public boolean addAll(Collection c) {
count += c.size();
return super.addAll(c);
}
public int getCount() {
return count;
}
}
public class ForwardingSet<E> implements Set {
private final Set<E> set;
public ForwardingSet(Set<E> set){
this.set=set;
}
@Override
public int size() {
return set.size();
}
@Override
public boolean isEmpty() {
return set.isEmpty();
}
@Override
public boolean contains(Object o) {
return set.contains(o);
}
@Override
public Iterator iterator() {
return set.iterator();
}
@Override
public Object[] toArray() {
return set.toArray();
}
@Override
public boolean add(Object o) {
return set.add((E) o);
}
@Override
public boolean remove(Object o) {
return set.remove(o);
}
@Override
public boolean addAll(Collection c) {
return set.addAll(c);
}
@Override
public void clear() {
set.clear();
}
@Override
public boolean removeAll(Collection c) {
return set.removeAll(c);
}
@Override
public boolean retainAll(Collection c) {
return set.retainAll(c);
}
@Override
public boolean containsAll(Collection c) {
return set.containsAll(c);
}
@Override
public Object[] toArray(Object[] a) {
return set.toArray();
}
}
CustomHashSet
์ Set ์ธํฐํ์ด์ค๋ฅผ implementsํ ForwardingSet
์ ์์ํ๋ค.
์ด๋ก์จ, HashSet์ ๋ถ๋ชจํด๋์ค์ ์ํฅ์ ๋ฐ์ง ์๊ณ ์ค๋ฒ๋ผ์ด๋ฉ์ ํตํด ์ํ๋ ์์ ์ ์ํํ ์ ์๊ฒ ๋๋ค.
public class Main {
public static void main(String[] args) {
CustomHashSet<String> customHashSet = new CustomHashSet<>(new HashSet<>());
List<String> test = Arrays.asList("a","b","c");
customHashSet.addAll(test);
System.out.println(customHashSet.getCount()); // 3
}
}
CustomHashSet
์ด ์ํ๋ ์์
์ ํ ์ ์๋๋ก ๋์์ค ForwardingSet
์ ์์(Delegation) ์ญํ ์ ๊ฐ์ง๋ค.
์๋ณธ ํด๋์ค๋ฅผ wrapping ํ๋๊ฒ ๋ชฉ์ ์ด๋ฏ๋ก, Wrapper Class๋ผ๊ณ ๋ถ๋ฅผ ์๋ ์์ ๊ฒ์ด๋ค.
๊ทธ๋ฆฌ๊ณ ํ์ฌ ์์
ํ ์ด๋ฌํ ํจํด์ ๋ฐ์ฝ๋ ์ดํฐ ํจํด
์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. ์ด๋ ํ ํด๋์ค๋ฅผ Wrapper ํด๋์ค๋ก ๊ฐ์ธ๋ฉฐ, ๊ธฐ๋ฅ์ ๋ง์์ด๋ค๋ ์๋ฏธ๋ค.
์์์ ์ฐ์ง๋ง๋ผ๋ ์ด์ผ๊ธฐ๋ ์๋๋ค. ์์์ ์ฌ์ฉํ๋ ์ํฉ์ LSP ์์น์ ๋ฐ๋ผ IS-A ๊ด๊ณ๊ฐ ๋ฐ๋์ ์ฑ๋ฆฝํ ๋๋ง ์ฌ์ฉํด์ผ ํ๋ค. ํ์ง๋ง ํ์ค์ ์ผ๋ก ์ถํ์ ๋ณํ๊ฐ ์ด๋ฃจ์ด์ง ์ ์๋ ๋ฐฉํฅ์ฑ์ ๊ณ ๋ คํด๋ดค์ ๋ ์ด๋ ๊ฒ ๋ช ํํ IS-A ๊ด๊ณ๋ฅผ ์ฑ๋ฆฝํ๋ค๊ณ ๋ณด์ฅํ ์ ์๋ ๊ฒฝ์ฐ๊ฐ ๋๋ถ๋ถ์ด๋ค.
๊ฒฐ๊ตญ ์ด๋ฐ ๋ฌธ์ ๋ฅผ ํผํ๊ธฐ ์ํด์ , ์ปดํฌ์ง์ ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๊ฐ์ฒด ์งํฅ์ ์ธ ์ค๊ณ๋ฅผ ํ ๋ ์ ์ฐํจ์ ๊ฐ์ถ๊ณ ๋์๊ฐ ์ ์์ ๊ฒ์ด๋ค.