Comments 14
Во-первых, «URL» обладает некоторыми частями, без которых он, как было обозначено в начале, перестает иметь смысл – это scheme и host.
кажется, что это уже ошибка. "/etc/passwd" – нормальный валидный ur
"/etc/passwd" – нормальный валидный ur
Это не так, согласно RFC3986: «The scheme and path components are required».
> The URLs employed by the NSURL class are described in RFC 1808, RFC 1738, and RFC 2732.
и, похоже, что единственной обязательной частью является scheme
Паттерн "Строитель" не нужен, если язык поддерживает передачу аргументов в функцию по имени и значения аргументов по-умолчанию.
Swift поддерживает и то и другое.
Паттерн билдер можно заменить на более простую функцию, без потери читаемости.
import Foundation
enum URLBuilderError: Error {
case emptyHost
case inconsistentCredentials
case systemError
}
func buildUrl(
user: String? = nil,
password: String? = nil,
host: String? = nil,
port: Int? = nil,
path: String = "",
queryItems: [String: String]? = [String: String](),
scheme: String = "https"
) throws -> URL {
guard let host = host else {
throw URLBuilderError.emptyHost
}
if user != nil {
guard password != nil else {
throw URLBuilderError.inconsistentCredentials
}
}
if password != nil {
guard user != nil else {
throw URLBuilderError.inconsistentCredentials
}
}
var urlComponents = URLComponents()
urlComponents.scheme = scheme
urlComponents.user = user
urlComponents.password = password
urlComponents.host = host
urlComponents.port = port
urlComponents.path = path
urlComponents.queryItems = queryItems?.map {
URLQueryItem(name: $0, value: $1)
}
guard let url = urlComponents.url else {
throw URLBuilderError.systemError // Impossible?
}
return url
}
Фабричная функция потом может быть вызвана вот так:
_ = try buildUrl(
user: "admin",
password: "Qwerty",
host: "somehost.com",
port: 80,
path: "/some/path",
queryItems: ["page": "0"])
URL
, а о конкретном шаблоне. Так сказать, познавательный, «для самых маленьких».P.S. Я бы назвал ваш метод makeURL() – так будет по официальному код-стайлу.
Если речь идет о шаблонах программирования, то человек явно не "самый маленький".
Можно изучить все паттерны и потом каждый день их применять. Однако смысл паттернов не в том, чтобы код написать, а чтобы добиться каких-то целей.
В случае со "Строителем" — поудобней сконструировать объект. Я сейчас помню три цели
- При конструировании сложного объекта, наглядно описать какое значение в какое свойство класса будет помещено.
- Предотвратить создание телескопических конструкторов для всех возможных инвариантов класса.
- Дать возможность строить объект в несколько разделенных этапов.
Вы показали только первую цель, причем неоптимально. Писать строителя для уточнения параметров нецелесообразно, если аргументы можно передавать по имени.
Иллюстрацию для второй цели вы не дали, но для ее достижения тоже нет смысла реализовывать шаблон "Строитель". Аргументам можно дать значения по-умолчанию.
Иллюстрацию для третьей цели вы тоже не дали, хотя для нее, этот шаблон реально помогает. Но такой случай очень редкий.
Архитектурный шаблон «Строитель» во вселенной «Swift» и «iOS»/«macOS»