Decorator

godo·2022년 8월 18일
0

Swift - Design Patterns

목록 보기
8/24

상속 없이 행동이나 기능을 특정한 객체에 추가할 수 있게 하는 것

Custom String Builder

class CodeBuilder : CustomStringConvertible
{
    private var buffer: String = ""
    
    init() {}
    init(_ buffer: String)
    {
        self.buffer = buffer
    }
    
    func append(_ s: String) -> CodeBuilder
    {
        buffer.append(s)
        return self
    }
    
    func appendLine(_ s: String) -> CodeBuilder
    {
        buffer.append("\(s)\n")
        return self
    }
    
    static func +=(cb: inout CodeBuilder, s: String)
    {
        cb.buffer.append(s)
    }
    
    var description: String
    {
        return buffer
    }
    
}

func main()
{
    var cb = CodeBuilder()
//    cb.append("glass").append("grass")
    cb.appendLine("class glass")
        .appendLine("{")
    
    cb += " // testing!\n"
    
    cb.appendLine("}")
    print(cb)
}

Multiple Inheritance

protocol ICanFly
{
    func fly()
}

protocol ICanCrawl
{
    func crawl()
}


class Bird: ICanFly
{
    func fly(){}
}

class Lizard: ICanCrawl
{
    func crawl(){}
}

class Dragon: ICanFly, ICanCrawl
{
    private let bird = Bird()
    private let lizard = Lizard()
    
    func fly()
    {
        bird.fly() // delegation
    }
    
    func crawl()
    {
        lizard.crawl()
    }
}

Dynamic Decorator Composition

protocol Shape : CustomStringConvertible
{
    var description: String { get }
}

class Circle: Shape
{
    private var radius: Float = 0
    
    init(_ radius: Float)
    {
        self.radius = radius
    }
    
    func resize(_ factor: Float)
    {
        radius *= factor
    }
    
    var description: String
    {
        return "A circle of radius \(radius)"
    }
}


class Square : Shape
{
    private var side : Float = 0
    
    init(_ side: Float)
    {
        self.side = side
    }
    
    var description: String
    {
        return "A square with side \(side)"
    }
}

class ColoredShape : Shape
{
    var shape : Shape
    var color : String
    
    init(_ shape: Shape, _ color: String)
    {
        self.shape = shape
        self.color = color
    }
    
    var description: String
    {
        return "\(shape) has color \(color)"
    }
}

class TransparentShape: Shape
{
    var shape: Shape
    var transparency: Float
    
    init(_ shape: Shape, _ transparency: Float)
    {
        self.shape = shape
        self.transparency =  transparency
    }
    
    var description: String
    {
        return "\(shape) has \(transparency*100) % transparency"
    }
}


func main()
{
    let square = Square(1.89)
    print(square)
    
    let blueSquare = ColoredShape(square, "blue")
    print(blueSquare)
    
    let blueHalfTransparentSquare = TransparentShape(square, 0.5)
    print(blueHalfTransparentSquare)
}

Static Decorator Composition

protocol Shape : CustomStringConvertible
{
    init()
    var description: String { get }
}

class Circle: Shape
{
    private var radius: Float = 0
    
    required init() {}
    
    init(_ radius: Float)
    {
        self.radius = radius
    }
    
    func resize(_ factor: Float)
    {
        radius *= factor
    }
    
    var description: String
    {
        return "A circle of radius \(radius)"
    }
}


class Square : Shape
{
    private var side : Float = 0
    
    required init(){}
    
    init(_ side: Float)
    {
        self.side = side
    }
    
    var description: String
    {
        return "A square with side \(side)"
    }
}

class ColoredShape<T> : Shape where T : Shape
{
    private var shape : T = T()
    private var color : String = "black"
    
    required init(){}
    
    init(_ color: String)
    {
        self.color = color
    }
    
    var description: String
    {
        return "\(shape) has color \(color)"
    }
}

class TransparentShape<T>: Shape where T : Shape
{
    private var shape: T = T()
    private var transparency: Float = 0
    
    required init(){}
    
    init(_ transparency: Float)
    {
        self.transparency =  transparency
    }
    
    var description: String
    {
        return "\(shape) has \(transparency*100) % transparency"
    }
}


func main()
{

    let purpleCircle = ColoredShape<Circle>("purple")
    print(purpleCircle)
    
    let purpleHalfSquare = TransparentShape<ColoredShape<Square>>(0.4)
    print(purpleHalfSquare)
}

연습

Static Decoration Composition 활용

protocol shape: CustomStringConvertible
{
    init()
    var description: String { get }
}

protocol canFly : shape
{
    func fly() -> String
}

protocol canCrawl : shape
{
    func crawl() -> String
}

class Bird: canFly
{
    var age = 0
    
    required init() {}
    
    func fly() -> String
    {
        return (age < 10) ? "flying" : "too old"
    }
    
    var description: String
    {
        return "Bird's age is \(age) and \(fly())"
    }
}

class Lizard: canCrawl
{
    var age = 0
    
    
    required init() {}
    
    func crawl() -> String
    {
        return (age > 1) ? "crawling" : "too young"
    }
    
    var description: String
    {
        return "Lizard's age is \(age) and \(crawl())"
    }
}

class Dragon<T>: canFly, canCrawl where T : shape
{
    // todo: reuse bird/lizard functionality here
    
    private var shape : T = T()
    
    required init() {}
        
    var age: Int = 0
    func fly() -> String { return "dragon Flying" }
    func crawl() -> String { return "dragon Crawling" }
    
    var description: String
    {
        return "\(shape)"
    }
}

func main()
{
    let LizardDragon = Dragon<Lizard>()
    print(LizardDragon)
    
    let BirdDragon = Dragon<Bird>()
    print(BirdDragon)
}

Multiple Inheritance 활용

class Dragon
{
    
    private var _age = 0
    private let bird = Bird()
    private let lizard = Lizard()
    // todo: reuse bird/lizard functionality here
    
    var age: Int {
        get { return _age }
        set(value)
        {
            lizard.age = value
            bird.age = value
            _age = value
        }
    }
    func fly() -> String { return bird.fly() }
    func crawl() -> String { return lizard.crawl() }
}


func main()
{
    let dragon = Dragon()
    print("age: "+"\(dragon.age)")
    print(dragon.fly())
    print(dragon.crawl())
    print("\n")
    dragon.age = 10
    print("age: "+"\(dragon.age)")
    print(dragon.fly())
    print(dragon.crawl())
}

정리

Swift 에선 제약사항이 있어서 특정한 Decorator 방식을 C++에서와 같이 효율적이게 쓰는 건 힘들다.

profile
☀️☀️☀️

0개의 댓글