티스토리 뷰

Paradigm/OOP

[OOP] Open-Closed Principle

Mr.SIM 2013. 10. 28. 22:18

OCP(Open Closed Principle)는 확장에는 열려있되, 수정에는 닫혀있어야한다는 디자인 원칙이다. 게임 캐릭터에서 궁수라는 캐릭터를 예를들어 설명해보겠다.


아래 클래스는 아처(캐릭터) 클래스와 활(무기) 클래스이다.    

public class Archer { 
	private Bow bow; 
	private int level;
	
	public Archer(int level) {
		bow = new Bow();
		this.level = level;
	} 
	
	public void Attack(){
		StringBuilder sb = new StringBuilder();
		sb.append("Archer가 데미지 ");
		sb.append(getPower());
		sb.append("을(를) 입혔습니다."); 
		
		System.out.println(sb.toString());
	}
	
	public int getPower(){
		return (BowPower() * CharPower());
	}

	public int BowPower(){
		return bow.getPower();
	}
	
	public int CharPower(){
		return (int) (level * 0.1);
	}
} 

 
public class Bow {
	private int power;

	public Bow() {
		power = 50;
	}

	public int getPower() {
		return power;
	}
}

그리고 이를 사용하기 위한 메인 클래스

public class test {
	public static void main(String[] args) {

		Archer archer = new Archer(20);
		archer.Attack();
	}
}

만약 이런 코드가 있다면, 과연 이 코드는 객체지향적이라고 할 수 있을까? 만약에 아처가 칼을 든다고 하면? 아니면 석궁같은 일반적인 활과 다른 능력의 무기를 든다면 어떻게 바꾸어야할까, 결국, 아처클래스의 수정이 불가피할 것 있다. 이는 OCP에 어긋나는 일이다. 이를 해결하기 위해서는 Interface, abstract class를 사용함으로써 수정없이 사용할 수 있다. 


Bow라는 클래스와 Sword를 추상화시켜 Weapon이라는 interface를 구현하면, 무기를 추가하는데, 수정없이 추가가능하도록 할 수 있다.


우선 Weapon이라는 인터페이스를 만들고 Bow는 이를 구현하도록한다.

public interface Weapon { 
	public int getPower();
}
public class Bow implements Weapon{
	// 이전과 같다.
}

Archer라는 클래스에서 Bow를 Weapon으로 변경한다.

public class Archer { 
	private Weapon weapon; 
	private int level;
	
	public Archer(int level, Weapon weapon) {
		this.weapon = weapon;
		this.level = level;
	} 
	
	public void Attack(){
		StringBuilder sb = new StringBuilder();
		sb.append("Archer가 데미지 ");
		sb.append(getPower());
		sb.append("을(를) 입혔습니다."); 
		
		System.out.println(sb.toString());
	}
	
	public int getPower(){
		return (WeaponPower() * CharPower());
	}

	public int WeaponPower(){
		return weapon.getPower();
	}
	
	public int CharPower(){
		return (int) (level * 0.1);
	}
}

마지막으로 main()에서 레벨과 무기를 선택하고 Attack()하게 되면 이전 코드와 같은 결과값을 가지고 온다.

여기서 Sword라는 무기를 추가해보겠다.


public class Sword implements Weapon {
	private int power;

	public Sword() {
		power = 30;
	}

	@Override
	public int getPower() {
		return power;
	}

}

다음 코드에서 보듯이 다른 건 변하는 것없고, Sword라는 클래스를 추가할 수 있다.


public class test {
	public static void main(String[] args) {

		Archer Bow_archer = new Archer(20, new Bow());
		Archer Sword_archer = new Archer(20, new Sword());
		Bow_archer.Attack();
		Sword_archer.Attack();
	}
}


결과 값

Archer가 데미지 100을(를) 입혔습니다.

Archer가 데미지 60을(를) 입혔습니다.


** ___** ___ ** ___ ** ___ ** ___ ** ___ ** ___ ** ___ ** ___ ** ___ ** ___ ** ___ ** ___ ** ___ 
Archer라는 캐릭터 말고, 워리어가 등장한다면? 이 캐릭터또한 추상화시킬 필요가 있고, 같은 방법으로 해주면 OCP를 지킬 수 있을 것같다.


'Paradigm > OOP' 카테고리의 다른 글

[OOP] Liskov Substitution Principle  (0) 2013.10.29
[OOP] Single Responsibility Principle  (0) 2013.10.29
[OOP] 객제지향, 디자인 원리  (0) 2013.09.27
[OOP] SRP 확인하기  (0) 2013.09.27
[OOP] MVC패턴익히기  (0) 2013.06.06
댓글
최근에 올라온 글
최근에 달린 댓글
글 보관함
Total
Today
Yesterday