초기화시 한 번에 너무 많은 인자를 한꺼번에 주게 된다면 당연히 비효율적이게 되겠죠.
이때 사용하는 방식입니다.
func main()
{
let hello = "hello"
var result = "<p>\(hello)</p>"
print(result)
let words = ["hello","world"]
result = "<ul>\n"
for word in words
{
result.append("<li>\(word)</li>\n")
}
result.append("</ul>")
print(result)
}
main()
class HtmlElement: CustomStringConvertible
{
var name = ""
var text = ""
var elements = [HtmlElement]()
private let indentSize = 2
init() {}
init(name: String, text: String)
{
self.name = name
self.text = text
}
private func description(_ indent: Int) -> String
{
var result = ""
let i = String(repeating: " ", count: indent)
result += "\(i)<\(name)>\n"
if !text.isEmpty
{
result += String(repeating: " ", count: (indent+1))
result += text
result += "\n"
}
for e in elements
{
result += e.description(indent+1)
}
result += "\(i)</\(name)>\n"
return result
}
public var description: String
{
return description(0)
}
}
class HtmlBuilder: CustomStringConvertible
{
private let rootName : String
var root = HtmlElement()
init(rootName: String)
{
self.rootName = rootName
root.name = rootName
}
func addChild(name: String, text: String)
{
let e = HtmlElement(name: name, text: text)
root.elements.append((e))
}
var description: String
{
return root.description
}
func clear()
{
root = HtmlElement(name: rootName, text: "")
}
}
func main()
{
let builder = HtmlBuilder(rootName: "ul")
builder.addChild(name: "li", text: "hello")
builder.addChild(name: "li", text: "word")
print(builder)
}
func addChildFluent(name: String, text: String) -> HtmlBuilder
{
let e = HtmlElement(name: name, text: text)
root.elements.append((e))
return self
}
...
builder.addChildFluent(name: "li", text: "hello")
.addChild(name: "li", text: "word")
이런 식으로도 코드를 구현하는 게 가능합니다.
class Person : CustomStringConvertible
{
// address
var streetAddress = "", postcode = "", city = ""
// employment
var companyName = "", position = ""
var annualIncome = 0
var description: String
{
return "I live at \(streetAddress), \(position), \(city)." +
"I work at \(companyName) as a \(position), earning \(annualIncome)"
}
}
class PersonBuilder
{
var person = Person()
var lives : PersonAddressBuilder
{
return PersonAddressBuilder(person)
}
var works : PersonJobBuilder
{
return PersonJobBuilder(person)
}
func build() -> Person
{
return person
}
}
class PersonJobBuilder : PersonBuilder
{
internal init(_ person: Person)
{
super.init()
self.person = person
}
func at(_ companyName: String) -> PersonJobBuilder
{
person.companyName = companyName
return self
}
func asA(_ position: String) -> PersonJobBuilder
{
person.position = position
return self
}
func earning(_ annualIncome: Int) -> PersonJobBuilder
{
person.annualIncome = annualIncome
return self
}
}
class PersonAddressBuilder : PersonBuilder
{
internal init(_ person: Person)
{
super.init()
self.person = person
}
func at(_ streetAddress: String) -> PersonAddressBuilder
{
person.streetAddress = streetAddress
return self
}
func withPostcode(_ postcode: String) -> PersonAddressBuilder
{
person.postcode = postcode
return self
}
func inCity(_ city: String) -> PersonAddressBuilder
{
person.city = city
return self
}
}
func main()
{
let pb = PersonBuilder()
let p = pb
.lives.at("123 Seoul road")
.inCity("Seoul")
.withPostcode("753")
.works.at("A Company")
.asA("developer")
.earning(1000)
.build()
print(p)
}
Builder 을 사용하면 좀 더 보기 좋게 초기화를 할 수 있습니다.