Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
🐝 Цепочка обязанностей — это поведенческий паттерн, позволяющий передавать запрос по цепочке потенциальных обработчиков, пока один из них не обработает запрос.
//: Playground - noun: a place where people can play
import UIKit
enum ChainResult {
case error(NSError)
case success
}
class ValidationValue {
let original: String?
var checkableValue: String = ""
init(original: String?) {
self.original = original
self.checkableValue = original ?? ""
}
}
protocol MiddlewareProtocol {
func check(value: ValidationValue) -> ChainResult
}
class Middleware: MiddlewareProtocol {
var next: Middleware?
let error = NSError(domain: "ru.alobanov", code: 1, userInfo: [NSLocalizedDescriptionKey: "Next chain was not devined"])
func link(with: Middleware) -> Middleware {
self.next = with
return with
}
func check(value: ValidationValue) -> ChainResult {
return checkNext(value: value)
}
func checkNext(value: ValidationValue) -> ChainResult {
return self.next?.check(value: value) ?? .error(error)
}
}
class PreparingMiddleware: Middleware {
override func check(value: ValidationValue) -> ChainResult {
let prep = value.original?.trimmingCharacters(in: CharacterSet.whitespaces) ?? nil
let secondPrep = (prep?.isEmpty ?? true) ? nil : prep
guard let preparingValue = secondPrep else {
let d = [NSLocalizedDescriptionKey: "Значение равно nil или пустое"]
let e = NSError(domain: "ru.alobanov", code: 1, userInfo: d)
return .error(e)
}
// final preparing value
value.checkableValue = preparingValue
return checkNext(value: value)
}
}
class RegExpMiddleware: Middleware {
private let regexp: String
init(regexp: String) {
self.regexp = regexp
}
override func check(value: ValidationValue) -> ChainResult {
if regex(str: value.checkableValue, pattern: self.regexp).isEmpty {
let d = [NSLocalizedDescriptionKey: "Валидация по регулярному выражению не пройдена"]
let e = NSError(domain: "ru.alobanov", code: 1, userInfo: d)
return .error(e)
}
return checkNext(value: value)
}
private func regex(str: String, pattern: String) -> [String] {
do {
let regex = try NSRegularExpression(pattern: pattern, options: NSRegularExpression.Options.caseInsensitive)
let nsstr = str as NSString
let all = NSRange(location: 0, length: nsstr.length)
var matches: [String] = [String]()
regex
.enumerateMatches(in: str, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: all) { (result: NSTextCheckingResult?, _, _) in
if let r = result {
let result = nsstr.substring(with: r.range) as String
matches.append(result)
}
}
return matches
} catch {
return [String]()
}
}
}
class FinalMiddleware: Middleware {
override func check(value: ValidationValue) -> ChainResult {
return .success
}
}
class ValidationTest {
func test() {
let value = ValidationValue(original: "lobanov.aw@gmail.com")
let validationChain = PreparingMiddleware()
let validationRegexp = RegExpMiddleware(regexp: "^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}")
let validationFinal = FinalMiddleware()
validationChain.link(with: validationRegexp).link(with: validationFinal)
let result = validationChain.check(value: value)
switch result {
case .error(let e):
print(e.localizedDescription)
default:
print("validation success")
}
}
}
let chain = ValidationTest()
chain.test()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.