Behavioral Design Pattern - Chain of Responsibility, Command Pattern, Iterator Pattern

kyle Kim·2022년 12월 24일
0

iOS개발

목록 보기
19/22

Behavioral Design Pattern은 Object들 간에 어떻게 커뮤니케이션을 할지, 그리고 다른 Object와 어떻게 구분할지를 구성해주는 디자인 패턴이다.

iOS 개발에서 사용되는 Behavioral Design Pattern을 다루겠다.

1. Chain of Responsibility

체인간에 요청을 할때 체인 핸들러가 요청을 처리하거나 전달할 수 있도록 해주는 Design Pattern이다.

예시

enum Rank: Int  {
	case bronze = 1
    case silver = 2
    case gold = 3
}

class Games {
	var rank: Rank
    
    init(rank: Rank) {
		self.rank = rank
    }
}

protocol GameManagement {
	var nextRankManagement: GameManagement? { get set}
    func manage(game: Games)
}

class BronzeGamePlay: GameManagement {
	var nextRank: GameManagement? { get set}
    
    func manage(game: Games) {
    	if game.rank.rawValue == 1 {
        	print("bronze management")
        } else {
        	nextRank?.manage(game: game)
        }
    }
}

class SilverGamePlay: GameManagement {
	var nextRankM: GameManagement? { get set}
    
    func manage(game: Games) {
    	if game.rank.rawValue == 2 {
        	print("silver management")
        } else {
        	nextRank?.manage(game: game)
        }
    }
}

class GoldGamePlay: GameManagement {
	var nextRank: GameManagement? { get set}
    
    func manage(game: Games) {
    	if game.rank.rawValue == 2 {
        	print("gold management")
        } else {
        	nextRank?.manage(game: game)
        }
    }
}

// 사용 예시
let bronzePlay = BronzeGamePlay()
let silverPlay = SilverGamePlay()
let goldPlay = GoldGamePlay()
bronzePlay.nextRank = silverPlay
silverPlay.nextRank = goldPlay

let gameSample = Game(rank: Rank.gold)
bronzePlay.manage(game: gameSample)

// output:
// gold management

Chain of Responsibility 장점

  • 요청자와 수행자가 직접 연결되는 것을 방지하기 때문에 유연하게 수정하거나 확장할 수가 있다.

Chain of Responsibility 단점

  • 많은 implementation이 필요하다.
  • 계층이 늘어나면 늘어날수록 디버깅하거나 유지보수하기에 힘들 수도 있다.

2. Command Pattern

요청을 하나의 객체로 캡슐화, 추상화 하여 여러 기능을 사용할 수 있게 해주는 Design Pattern이다.

예시

// 실행될 요청에 대한 인터페이스
protocol Command {
	func execute()
}

// 실제 요청에 대해 구현하는 클래스
class SampleCommand: Command {
	private var receiver: Receiver
    
    init(receiver: Receiver) {
    	self.receiver = receiver
    }
    
	func execute() {
    	self.receiver.action()
    }
}

// 수신자 클래스 
class Receiver {
	func action() {
    	print("Receiver action")
    }
}

// 실행을 요청하는 클래스
class Invoker {
	private var start?
    func setStart(command: Command) {
    	start = command
    }
    
    func executeCommand() {
    	start?.execute()
    }
}


// 사용 예시
let invoker = Invoker()
let receiver = Receiver()
let sampleCommand = SampleCommand(receiver: receiver)
invoker.setStart(command: sampleCommand)

invoker.executeCommand()


// Output
// working

Command Pattern 장점

  • invoker와 receiver 사이의 의존성을 분리한다.
  • 요청 추가에 유리하다.

Command Pattern 단점

  • 많은 implementation이 필요하다. 그래서 개발할때 정확하게 구현해야하는 주의가 필요하다.

3. Iterator Pattern

콜렉션의 자료구조를 노출하지 않고 해당 항목에 접근할 수 있게 해주는 Design Pattern이다.

예시

struct UserCars: Sequence {
	let cars: [String]
    
    func makeIterator() {
    	return UserCarsIterator(cars: cars)
    }
}

struct UserCarsIterator: IteratorProtocol {
	var cars: [String]
    var index: Int = 0
    
    init(cars: [String]) {
    	self.cars = cars
    }
    
    
// struct 내부 자원의 수정이 필요하기 때문에 mutating 사용
    mutating func next() -> String? {
    	if cars.count > index {
        	let result = cars[index]
            index += 1
        	return result
        } else {
        	return nil
        }        
    }
}

// 사용 예시
let userCars = UserCars(cars: ["Tesla", "Hyundai", "Lexus"])
for car in userCars {
	print(car)
}

// Output
// Tesla
// Hyundai
// Lexus

Iterator Pattern 장점

  • collection을 추가할때 기존의 코드를 사용하면 된다.

Iterator Pattern 단점

  • 단순한 collection일 경우에는 사용할 필요가 없다.
profile
가고일(gagoil)의 개발일지

0개의 댓글