[์ค์ํํธ ๋์์ธํจํด] ์ ๋ต ํจํด(Strategy Pattern)
์ ๋ต ํจํด(Strategy Pattern)
์ ๋ต ํจํด์ ์๊ณ ๋ฆฌ์ฆ์ ์งํฉ(Algorithm Family)์ ์ฌ์ฉํ๋ ํ์ ํจํด์ ๋๋ค. ์ฌ๋ฌ ์๊ณ ๋ฆฌ์ฆ์ ๊ฐ๊ฐ ๊ฐ์ฒด๋ก ์บก์ํํ๊ณ , ๋์ผํ ๋ชฉ์ ์ ํ๋ ์๊ณ ๋ฆฌ์ฆ๋ค์ ํ๋์ ์ธํฐํ์ด์ค๋ก ๋ฌถ์ต๋๋ค. ๊ทธ๋ฌ๋ฉด ์ด ์๊ณ ๋ฆฌ์ฆ๋ค์ด ํด๋ผ์ด์ธํธ ๊ฐ์ฒด์์ ๊ต์ฒด๋๋ฉด์ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค. ๋ฐ๋ผ์ ์๊ณ ๋ฆฌ์ฆ์ด ํด๋ผ์ด์ธํธ ๊ฐ์ฒด์ ๋ ๋ฆฝ์ ์ผ๋ก ๊ตฌ์ฑ๋๊ธฐ ๋๋ฌธ์ ๋์จํ ์ฐ๊ฒฐ(Decoupling)์ ๋ง๋ค ์ ์์ฃ .
๋์จํ๊ฒ ์ฐ๊ฒฐ๋๋ค๋ ๊ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๊ฐ ์๊ณ ๋ฆฌ์ฆ์ด ๋ณํ๊ฒ ๋ ๋, ์ํฅ์ ๋ฐ์ง ์๊ฒ ๋๋ค๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋ง์ฝ ์ด๋ค ์๊ณ ๋ฆฌ์ฆ์ด ์์ ๋์ด์ผ ํ๋ค๋ฉด, ์บก์ํ๋ ํด๋น ์๊ณ ๋ฆฌ์ฆ๋ง ์์ ํ๊ฒ ๋๊ณ , ๋ด๋ถ์ ์ผ๋ก ์ด๋ป๊ฒ ์์ ๋๊ณ ์ด๋ป๊ฒ ๊ตฌํ๋์ด ์๋์ง ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ ์์ง ๋ชปํฉ๋๋ค.
์๋ฅผ ๋ค์ด๋ด ์๋ค.
์ด๋ค ๋ฌธ์์ด์ด ๋ค์ด์์ ๋, ์กฐ๊ฑด์ ๊ฒ์ฌํด์ฃผ๋ Validator ๊ฐ์ฒด๊ฐ ์๋ค๊ณ ํด๋ณผ๊ฒ์. ์ฒ์์๋ ๋ณ ๋ฌธ์ ๊ฐ ์๊ฒ ์ง๋ง, ๋ง์ฝ ์ถ๊ฐ์ ์ธ ์๊ตฌ์ฌํญ์ด ์๊ฒจ์ ์๊ณ ๋ฆฌ์ฆ์ด ์ถ๊ฐ๋๋ค๋ฉด ์ด๋จ๊น์? ๊ทธ๋ ์ฐ๋ฆฌ๋ ์๋ง๋ Validator ๊ฐ์ฒด์ ์๋ก์ด ์๊ณ ๋ฆฌ์ฆ์ ์ถ๊ฐํ๊ฒ ์ฃ .
ํ์ง๋ง ์ด๋ฐ ๋ฐฉ๋ฒ์ ๊ฐ๋ฐฉ ํ์ ์์น(OCP)์ ์ด๊ธ๋ฉ๋๋ค. ๊ธฐ์กด ๊ฐ์ฒด์ ๋ณ๊ฒฝ์ฌํญ์ด ์๊ธฐ๊ธฐ ๋๋ฌธ์ด์ฃ .
๋ฐ๋ผ์ ์ ๋ต ํจํด์ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ ์๊ณ ๋ฆฌ์ฆ ์งํฉ์ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ์ง๊ณ , ๊ตฌ์ฒด์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ ํ์์ ๋ฐ๋ผ ์ฃผ์ ํ๊ฒ ํฉ๋๋ค.
์ด๋ฐ ๋์์ธ ํจํด์ ์ฌ์ฉํ๋ฉด ๋ง์ฝ ์๋ก์ด ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ Validator๊ฐ ์์คํค ์ฝ๋๋ฅผ ๊ฒ์ฌํ๊ฒ ๋๋ค๊ณ ํ๋๋ผ๋ ์๋์ ๊ฐ์ด ๊ตฌ์ฑํ๋ ๊ฒ์ ํตํด์ ๊ฐ๋ฐฉ ํ์ ์์น์ ์งํฌ ์ ์์ต๋๋ค.
๊ตฌํํด๋ณด๊ธฐ
๊ทธ๋ผ ์์์ ์ ๋ฆฌํ ์ปจ์ ์ ๊ทธ๋๋ก ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ , ํด๋ผ์ด์ธํธ ๊ฐ์ฒด์ ์๊ณ ๋ฆฌ์ฆ์ ์ธํฐํ์ด์ค๊ฐ ๋ ํ๋กํ ์ฝ์ ์ ์ํ ๊ฒ์.
protocol Validatable {
func validate(text: String) -> Bool
}
protocol Validator {
var validationStrategy: Validatable { get set }
func validate(text: String) -> Bool
}
Validatable ํ๋กํ ์ฝ์ ์๊ณ ๋ฆฌ์ฆ์ ์ธํฐํ์ด์ค๊ฐ ๋ ํ๋กํ ์ฝ์ ๋๋ค. validate ๋ฉ์๋๋ฅผ ์ ์ํ๊ณ ์๊ณ , ์ธ์๋ก ๋ฌธ์์ด์ ๋ฐ์ผ๋ฉด ์ ์ ํ ์๊ณ ๋ฆฌ์ฆ์ ์ํํ ๋ค์ Bool ํ์ ๊ฐ์ ๋ฐํํ๋๋ก ๊ฐ์ ํ๊ณ ์์ด์. ์ ๋ต์ ํด๋นํ๋ ๊ฐ ์๊ณ ๋ฆฌ์ฆ๋ค์ ์ด ํ๋กํ ์ฝ์ ์ฑํํด validate๋ฅผ ๊ตฌํํ๋ฉด ๋๊ฒ ์ฃ .
Validator ํ๋กํ ์ฝ์ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด์ ๋ด๋ถ์ ๋ํ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ ํ๋กํ ์ฝ์ ๋๋ค. validationStrategy ํ๋กํผํฐ๋ฅผ ํตํด์ Validatable ํ์ , ์ฆ, ๊ฒ์ฆ์ ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ์ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ Validator๋ validation ๋ฉ์๋๋ฅผ ๊ฐ์ง๋๋ฐ์, ์ด๋ฒ์๋ ์ค์ ๋ก ์ฌ์ฉ์๊ฐ ํธ์ถํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๊ฒ ๋ ๋ฉ์๋์ ๋๋ค.
final class StringValidator: Validator {
var validationStrategy: Validatable
init(strategy: Validatable) {
self.validationStrategy = strategy
}
func change(strategy: Validatable) {
self.validationStrategy = strategy
}
func validate(text: String) -> Bool {
return validationStrategy.validate(text: text)
}
}
์ด์ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด์ ๊ตฌ์ฒดํ์ ์ ์ ์ํ์ต๋๋ค. StringValidator๋ Validator ํ๋กํ ์ฝ์ ์ฑํํด ๊ตฌํํ๊ณ ์๋๋ฐ์, validate ๋ฉ์๋๋ฅผ ํตํด ๊ฒ์ฆ ์๊ณ ๋ฆฌ์ฆ์ ์ํํ๊ณ , change ๋ฉ์๋๋ฅผ ํตํด ํ์ฌ ์ฌ์ฉํ๋ ์๊ณ ๋ฆฌ์ฆ์ ๋ค๋ฅธ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ๋ณ๊ฒฝํ ์ ์๊ฒ ํฉ๋๋ค.
์ฌ๊ธฐ์ ๊ฐ์ฅ ์ค์ํ validate ๋ฉ์๋๋ฅผ ๋ค์ ๋ณผ๊ฒ์.
func validate(text: String) -> Bool {
return validationStrategy.validate(text: text)
}
validate ๋ฉ์๋๋ ๋ด๋ถ์ ์ด๋ค ์๊ณ ๋ฆฌ์ฆ๋ ๊ฐ์ง์ง ์์์. ๋์ ์์ ์ด ๊ฐ์ง๊ณ ์๋ ์๊ณ ๋ฆฌ์ฆ ์ ๋ต(validationStrategy)๊ฐ ๊ฐ์ง ์๊ณ ๋ฆฌ์ฆ์ ์คํํด์ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋๋ก ๋ฐํํ์ฃ . ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํ๊ณผ ๊ทธ ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํ๋ ๊ฐ์ฒด๊ฐ ์์ ํ๊ฒ ๋ถ๋ฆฌ๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ๊ตฌํํด์ฃผ์ด์ผ๊ฒ ์ฃ ?
class NumberValidator: Validatable {
func validate(text: String) -> Bool {
return text.allSatisfy({ $0.isNumber })
}
}
class LengthValidator: Validatable {
func validate(text: String) -> Bool {
return text.count < 10
}
}
์ผ๋จ Validatable์ ์ฑํํ๋ ๋ ๊ฐ์ ํ์ ์ ๋ง๋ค์์ด์. ๊ทธ๋ฆฌ๊ณ ๊ฐ๊ฐ ๋ฌธ์์ด์ ๋ชจ๋ ๋ฌธ์๊ฐ ์ซ์์ธ์ง ํ์ธํ๋ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋ฌธ์์ด์ ๊ธธ์ด๊ฐ 10 ๋ฏธ๋ง์ธ์ง ํ์ธํ๋ ์๊ณ ๋ฆฌ์ฆ์ ์ ์ํด์ฃผ์์ต๋๋ค.
let validator = StringValidator(strategy: LengthValidator())
print(validator.validate(text: "12345678910")) // false
validator.change(strategy: NumberValidator())
print(validator.validate(text: "12345678910")) // true
ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ๋๋ ์์ฑ์๋ฅผ ํตํด ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ์ ์ฃผ์ ํ๊ฑฐ๋, change ๋ฉ์๋๋ฅผ ํตํด ์ฌ์ฉํ ์๊ณ ๋ฆฌ์ฆ์ ๋ณ๊ฒฝํฉ๋๋ค.
์๋ก์ด ์ ๋ต์ ์ถ๊ฐ
๊ฝค ๊ฐ๋จํ๊ฒ ์ ๋ต ํจํด์ ๊ตฌํํ ์ ์์๋๋ฐ์, ์ด๋ฒ์๋ ์์์ ์ ๋ฆฌํ๋ฉด์ ์ด์ผ๊ธฐํ๋๋๋ก ์๋ก์ด ์๊ตฌ์ฌํญ์ด ํ๋ ์ถ๊ฐ๋์๋ค๊ณ ํด๋ณด๊ฒ ์ต๋๋ค. ์ด๋ฒ์๋ StringValidator๊ฐ ๋ฌธ์์ด์ ๋ชจ๋ ๋ฌธ์๊ฐ ์์คํค ์ฝ๋๋ก ํํ์ด ๊ฐ๋ฅํ์ง ํ์ธํ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์ถ๊ฐ๋์ด์ผ ํด์.
class AsciiValidator: Validatable {
func validate(text: String) -> Bool {
return text.allSatisfy({ $0.isASCII })
}
}
๋ฐ๋ผ์ Validatable์ ์ฑํํ๋ ์๊ณ ๋ฆฌ์ฆ์ ์บก์ํํ ๊ฐ์ฒด๋ฅผ ์๋ก ํ๋ ๋ง๋ค๊ณ ,
validator.change(strategy: AsciiValidator())
print(validator.validate(text: "12345678910")) // true
ํด๋ผ์ด์ธํธ ๊ฐ์ฒด์ ์ฃผ์ ํด์ฃผ๊ธฐ๋ง ํ๋ฉด ์๋ก์ด ์๊ตฌ์ฌํญ์ ๋ง์กฑ์ํฌ ์ ์์ต๋๋ค. ๋ง์ฝ ์ถ๊ฐํด์ผํ๋ ์๊ณ ๋ฆฌ์ฆ์ด ์์ญ๊ฐ์ง๋ผ๋ฉด ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์์ ํ์ง ์๊ณ ์ฝ๊ฒ ์๊ณ ๋ฆฌ์ฆ์ ์ถ๊ฐํ ์ ์๊ฒ ์ฃ .
๋ง์ฝ ๋ชจ๋ ์๊ณ ๋ฆฌ์ฆ์ ํ๋ฒ์ ์ํํด์ผํ๋ค๊ณ ํ๋๋ผ๋ ์๋์ฒ๋ผ ์ฒ๋ฆฌํ ์ ์์ผ๋๊น์.
func validateAll(text: String) -> Bool {
let strategies: [Validatable] = [LengthValidator(), NumberValidator(), AsciiValidator()]
return strategies.filter({ strategy in
return StringValidator(strategy: strategy).validate(text: text)
}).isEmpty
}
print(validateAll(text: "12345678910")) // false
์ ๋ฆฌ
์ ๋ต ํจํด์ ์๊ณ ๋ฆฌ์ฆ๋ค์ ์บก์ํํด์ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ก๋ถํฐ ๋ถ๋ฆฌํ๊ณ , ๊ฐ์ ๋ชฉ์ ์ ์๊ณ ๋ฆฌ์ฆ๋ค์ ํ๋์ ์ธํฐํ์ด์ค๋ก ๋ฌถ์ด ๊ฐ์ฒด๊ฐ ํ์์ ๋ฐ๋ผ ์๊ณ ๋ฆฌ์ฆ์ ๊ต์ฒดํ ์ ์๊ฒ ํ๋ ๋์์ธ ํจํด์ด์์ต๋๋ค.
์๊ณ ๋ฆฌ์ฆ๊ณผ ํด๋ผ์ด์ธํธ๊ฐ ์์ ํ ๋ถ๋ฆฌ๋์ด ์๊ธฐ ๋๋ฌธ์ ๋ณ๊ฒฝ๊ณผ ํ์ฅ์ ์ ์ฐํ๊ณ OCP๋ฅผ ๋ฐ๋ฅด๋ ๋์์ธ ํจํด์ ๋๋ค. ์ฌ์ค ๋ฐ์ง๊ณ ๋ณด๋ฉด SRP, DIP, SIP, LSP๋ ๋ชจ๋ ๋ฐ๋ฅด๊ณ ์์ด์.
์๊ณ ๋ฆฌ์ฆ์ ์ํ์ ์บก์ํ๋ ์๊ณ ๋ฆฌ์ฆ ๊ฐ์ฒด์, ์๊ณ ๋ฆฌ์ฆ์ ์ ํ์ ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ก ๋๋๊ณ ์์ด ๋จ์ผ ์ฑ ์ ์์น(SRP)์ ๋ฐ๋ฅด๊ณ ,
ํด๋ผ์ด์ธํธ ๊ฐ์ฒด๋ ์๊ณ ๋ฆฌ์ฆ ์ธํฐํ์ด์ค์ ์์กดํ๊ธฐ ๋๋ฌธ์ ์์กด์ฑ ์ญ์ ์์น(DIP) ๋ฐ๋ฅด๊ฒ ๋ฉ๋๋ค.
์๊ณ ๋ฆฌ์ฆ์ ๊ฐ ์ธํฐํ์ด์ค๋ Alogrithm Family๋ฅผ ํํํ๊ธฐ ๋๋ฌธ์ ์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น(SIP)๋ ๋ฐ๋ฅด๊ณ ,
์ ์์ ์์๋ LSP๊ฐ ๋ช ํํ ๋ํ๋์ง๋ ์์ง๋ง, ์ธ์ ๋ ๊ฐ์ ์๊ณ ๋ฆฌ์ฆ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๊ฒ ๋๊ธฐ ๋๋ฌธ์ ํ์ ํ์ ๊ณผ ์์ ํ์ ์ด ์นํ ๊ฐ๋ฅํ ๋ฆฌ์ค์ฝํ ์นํ ์์น(LSP)์ ๋ฐ๋ฅด๊ฒ ๋ฉ๋๋ค.
์ ๋ต ํจํด์ ํ ๊ฐ์ฒด๊ฐ ๋น์ทํ ๋ชฉ์ ์ ๊ฐ์ง๋ ์ฌ๋ฌ ์๊ณ ๋ฆฌ์ฆ์ ๋ฐํ์์ ์ ํ์ ์ผ๋ก ์ฌ์ฉํ๊ฒ ๋ ๋ ๋ถ๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ค์ด๋ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ์ฉํด๋ณผ ์ ์์ ๊ฒ ๊ฐ์์.
'๐ฎ ์จ-์์ค > ๐ ๋์์ธํจํด' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋๊ธ
์ด ๊ธ ๊ณต์ ํ๊ธฐ
-
๊ตฌ๋
ํ๊ธฐ
๊ตฌ๋ ํ๊ธฐ
-
์นด์นด์คํก
์นด์นด์คํก
-
๋ผ์ธ
๋ผ์ธ
-
ํธ์ํฐ
ํธ์ํฐ
-
Facebook
Facebook
-
์นด์นด์ค์คํ ๋ฆฌ
์นด์นด์ค์คํ ๋ฆฌ
-
๋ฐด๋
๋ฐด๋
-
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
๋ค์ด๋ฒ ๋ธ๋ก๊ทธ
-
Pocket
Pocket
-
Evernote
Evernote