밤에 쓴 코드

OOP ) 상태 , 행동 , 식별자 본문

OOP

OOP ) 상태 , 행동 , 식별자

붱이🦉 2019. 4. 26. 17:49

OOP ) 상태 , 행동 , 식별자


  • 객체지향 패러다임

        지식을 추상화 하고 , 추상화한 지식을 객체내에 캡슐화 하여 복잡성을 관리하고 , 객체의 지식과 행동을 구조화
  • 객체

    • 하나의 단위로 인식가능한 사물이다.

    • 행동 , 상태 , 식별자를 가지는 사물


현실의 문제를 해결하기위해서 소프트웨어 세계를 창조합니다.

하나의 문제를 해결하기위해선 여러개의 작은 동작들로 나눌 수 있습니다.

각각의 동작들은 책임을 가지는 객체가 해결하고 , 협력을 통해 문제를 해결합니다.


  • 행동과 상태

    • 행동을 수행하는 객체들이 행동의 결과를 결정하는데에는 과거의 행동의 이력이 연관을 가진다.

    • 과거의 행동의 이력을 표현할 수 있는 효과적인 방법은 상태 로 표현하는 것이다.

    • 과거의 행동이 상태를 변경하므로 상태는 행동의 결과에 의존한다

    • 행동의결과는 상태에 의존한다

    • 플레이어가 하는 공격이라는 행동은 플레이어가 과거에 어떤 무기를 장착하는 동작을 했는 지에 따라 달라진다.
      과거의 무기를 장착하는 행동에 따라 달라지는 데 이걸 어떻게 공격하는 행동에 연관을 가지게 할것인가?
      상태 라는 개념이 생기면 편하다. 무기를 장착하는 행동은 플레이어의 공격력이라는 상태를 수정한다.
      그 수정한 공격력상태는 이후 있을 공격이라는 행동에 영향을 끼친다.
      이렇게 행동 -> 상태 -> 행동 이런 식으로 계속적으로 영향을 끼친다.

예) 게임내의 캐릭터와 몬스터간의 공격

  • GameObject

  • class GameObject{
        private(set) var hp : Int
        var attackPower : Int
        var defensePower : Int
        init(hp:Int,attackPower:Int,defensePower:Int){
            self.hp = hp
            self.attackPower = attackPower
            self.defensePower = defensePower
        }
        func attack(target: GameObject){
            target.damaged(amount: self.attackPower)
        }
        func damaged(amount:Int){
            let calculatedDamageAmount = amount - self.defensePower/10
            self.hp -= calculatedDamageAmount
        }
    }
  • Player

  • class Player:GameObject{
        var weapon : Weapon?
    
        init(hp: Int, attackPower: Int, defensePower: Int,weapon:Weapon = Weapon(originPower: 5, phaseOfReinforce: 0)) {
            super.init(hp: hp, attackPower:weapon.power ,defensePower: defensePower)
            self.weapon = weapon
        }
        override func attack(target: GameObject) {
            guard let monster = target as? Monster else {
                print("올바른 타겟이 아닙니다")
                return
            }
            super.attack(target: monster)
        }
    }
  • Weapon

  • struct Weapon {
        var power : Int { return originPower + phaseOfReinforce*10 }
        var originPower :Int
        var phaseOfReinforce : Int
        mutating func reinforce(){
            self.phaseOfReinforce+=1
        }
    }
  • Monster

  • class Monster : GameObject{
        override func attack(target: GameObject) {
            guard let player = target as? Player else {
                print("올바른 타겟이 아닙니다")
                return
            }
            super.attack(target: player)
        }
    }
  • World

  • let sward  = Weapon.init(originPower: 10, phaseOfReinforce: 0)
    let warrior = Player.init(hp: 100, attackPower: 5, defensePower: 10,weapon: sward)
    
    let bow = Weapon.init(originPower: 5, phaseOfReinforce: 0)
    let archer = Player.init(hp: 100, attackPower: 5, defensePower: 10,weapon: bow)
    
    let slime = Monster.init(hp: 50, attackPower: 5, defensePower: 5)
    
    warrior.attack(target: archer) //   올바른 타겟이 아닙니다
    warrior.attack(target: slime) //    slime.damage() 발생
  • 상태( hp )는 행동( damaged() ) 의 이력에 따라서 값이 변경된다.
        - 과거의 행동들이 상태를 변경한다.
    행동( attack() ) 의 결과는 상태( attackPower ) 에 의존한다.
        - 행동의 결과는 상태에 의존한다.
- 객체는 자율적이고 능동적이다
    - Weapon.reinforce() - 무기는 스스로 강화되지는 않지만, 객체는 모두 능동적으로 행동한다.
    - 외부에서는 메시지를 보낼뿐 상태는 객체 자신 스스로 결정한다.
  - 객체는 자신의 행동의 결과를 자신 스스로 자율적으로 결정하기 때문에 , 외부에는 상태를 노출 할 필요가 없다

식별자

  • 값을 표현하는 객체가 아닌 모두 식별자를 가진다.

  • 객체는 가변적이다.

  • 객체의 속성의 유무는 정적, 값은 동적으로 움직인다

    • hp 라는 속성 은 언제나 존재하나 , 수치는 바뀔수있다.
  • 이유?

    위에 말했듯이 객체는 가변적이다.
    항상 변하는 값으로 객체를 식별할 수 는 없다.
  • 예시

  • var monsterRed = Monster.init(hp: 50, attackPower: 5, defensePower: 5)
    var monsterBlue = Monster.init(hp: 50, attackPower: 5, defensePower: 5)
    // 둘은 동등한 능력을 가지나 , 분리된 객체이다.
    // 동등성은 만족하나 , 동일성은 만족하지 않는다.
    monsterRed.attackPower = 100
    // 동등성은 언제든지 깨질 수있다.

설계시 고려할 사항

행동을 먼저 결정하고 상태를 결정해라

  • 캡슐화를 저해할수 있다.

    • 상태를 먼저 결정하게되면 , 상태위주의 코드를 짜기때문에 , 상태를 캡슐화하는 것이 어렵다.
  • 협력을 저해할 수 있다.

    • 협력을 함에 있어서 객체들은 각각 자신에 책임에 맞는 행동을 구현하고 , 행동은 상태에 의존해야 한다.
  • 재사용을 방해할수 있다.


기타

  • 쿼리 : 객체의 상태를 조회 ex) getter

  • 명령 : 객체의 상태를 변경 ex) setter

'OOP' 카테고리의 다른 글

OOP ) SOLID - 객체지향 5원칙  (0) 2019.05.18
OOP ) 타입, 추상화  (0) 2019.04.28
OOP) 역할 , 책임 , 협력  (0) 2019.04.22
OOP ) Class,객체간의 소통  (0) 2019.04.07
OOP ) 클래스 / 인스턴스 / 객체  (0) 2019.04.02
Comments