第四周第一天

第四周第一天

协议,协议的语法

protocol Flyable {
    func fly()
}

protocol Fightable {
    func fight()
}

协议是方法的集合(计算属性相当于就是方法)
// 可以把看似不相关的对象的公共行为放到一个协议中
// 协议在Swift开发中大致有三种作用:
// 1. 能力 - 遵循了协议就意味着具备了某种能力
// 2. 约定 - 遵循了协议就一定要实现协议中的方法
// 3. 角色 - 一个类可以遵循多个协议, 一个协议可以被多个类遵循, 遵循协议就意味着扮演了某种角色, 遵循多个协议就意味着可以扮演多种角色
// Swift中的继承是单一继承(一个类只能有一个父类), 如果希望让一个类具备多重能力可以使用协议来实现(C++里面是通过多重继承来实现的, 这是一种非常狗血的做法)
协议的继承

class Boxer: Fightable {
    @objc func fight() {
        print("正在进行格斗.")
    }
}
class Bird: Flyable {

    func fly() {
        print("鸟儿扇动翅膀飞行.")
    }
}
class Airplane: Flyable {
    func fly() {
        print("飞机依靠空气动力学原理飞行.")
    }
}

协议的拓展也可以说协议的默认实现当在类中没有实现这个方法默认实现的方法
协议扩展 - 可以在协议扩展中给协议中的方法提供默认实现
也就是说如果某个类遵循了协议但是没有实现这个方法就直接使用默认实现
那么这个方法也就相当于是一个可选方法(可以实现也可以不实现)


extension Fightable {
    func fight() {
        print("正在打架")
    }
}

依赖倒转原则(面向协议编程)

  1. 声明变量的类型时应该尽可能使用协议类型
  2. 声明方法参数类型时应该尽可能使用协议类型
  3. 声明方法返回类型时应该尽可能使用协议类型
    协议的组合
let array: [protocol<Flyable, Fightable>] = [
    // Rocket(),
    // Bird(),
    Superman(),
    // Boxer()
    // Airplane()
]
//只有同时满足两个协议的类才可以
for obj in array {
    obj.fly()
    obj.fight()
}

协议中全是抽象概念(只有声明没有实现) 遵循协议的类可以各自对协议中的计算属性和方法给出自己的实现版本 这样当我们面向协议编程时就可以把多态的优势发挥到淋漓尽致 可以写出更通用更灵活的代码(符合开闭原则)

实现开闭原则最关键有两点:

  1. 抽象是关键(在设计系统的时候一定要设计好的协议);
  2. 封装可变性(桥梁模式 - 将不同的可变因素封装到不同的继承结构中)

接口(协议)隔离原则: 协议的设计要小而专不要大而全
协议的设计也要高度内聚

protocol Shape {
    var perimeter: Double { get }
    var area: Double { get }
    func draw()
}
class Triangle: Shape {
    var a: Double
    var b: Double
    var c: Double
    
    init(a: Double, b: Double, c: Double) {
        assert(a + b > c && b + c > a && a + c > b, "不能构成三角形")
        self.a = a
        self.b = b
        self.c = c
    }
    
    var perimeter: Double {
        get { return a + b + c }
    }
    
    var area: Double {
        get {
            let half = perimeter / 2
            return sqrt(half * (half - a) * (half - b) * (half - c))
        }
    }
    
    func draw() {
        print("△")
    }
    
}

协议的应用

#### //图书类的定义
import Foundation

/// 图书
class Book {
    var name: String
    var price: Double
    var type: String
    
    // 四人帮设计模式 - 策略模式
    var strategy: DiscountStrategy?
    
    /**
     初始化方法
     - parameter name:  书名
     - parameter price: 价格
     - parameter type:  类型
     */
    init(name: String, price: Double, type: String) {
        self.name = name
        self.price = price
        self.type = type
    }
    
    /// 减多少钱
    var discountValue: Double {
        get {
            if let s = strategy {
                return s.discount(price)
            }
            else {
                return 0
            }
        }
    }
    
    /// 折后价格
    var discountedPrice: Double {
        get { return price - discountValue }
    }
}


#### //写协议部分
import Foundation

/**
 *  打折策略协议
 */
protocol DiscountStrategy {
    
    /**
     计算折扣
     - parameter price: 原价
     - returns: 折扣的金额
     */
    func discount(price: Double) -> Double
}

/// 百分比折扣策略
class PercentageDiscount: DiscountStrategy {
    var percentage: Double
    
    init(percentage: Double) {
        self.percentage = percentage
    }
    
    func discount(price: Double) -> Double {
        return price * (1 - percentage)
    }
}

// 固定金额折扣策略
class FixedDiscount: DiscountStrategy {
    var fixedMoney: Double
    
    init(fixedMoney: Double) {
        self.fixedMoney = fixedMoney
    }
    
    func discount(price: Double) -> Double {
        return price >= fixedMoney ? fixedMoney : 0
    }
}

// 分段折后策略
class SegmentedDiscount: DiscountStrategy {
    
    func discount(price: Double) -> Double {
        if price < 20 {
            return 0
        }
        else if price < 50 {
            return 3
        }
        else if price < 100 {
            return 10
        }
        else {
            return 30
        }
    }
}
#### //实现和调用部分

import Foundation

let booksArray = [
    Book(name: "C语言程序设计", price: 24.0, type: "计算机"),
    Book(name: "名侦探柯南", price: 98.5, type: "漫画"),
    Book(name: "Swift从入门到住院", price: 35.8, type: "计算机"),
    Book(name: "黄冈数学密卷", price: 34.2, type: "教材"),
    Book(name: "中国股市探秘", price: 58.5, type: "金融")
]

let discountDict: [String: DiscountStrategy] = [
    "计算机": PercentageDiscount(percentage: 0.78),
    "教材": PercentageDiscount(percentage: 0.85),
    "漫画": SegmentedDiscount(),
    "科普": FixedDiscount(fixedMoney: 2)
]

var totalPrice = 0.0
var totalDiscount = 0.0
for book in booksArray {
    if let strategy = discountDict[book.type] {
        book.strategy = strategy
    }
    print("《\(book.name)》原价: ¥\(book.price)元")
    print("《\(book.name)》折后价: ¥\(book.discountedPrice)元")
    totalPrice += book.discountedPrice
    totalDiscount += book.discountValue
}

print(String(format: "总计: ¥%.1f元", totalPrice))
print(String(format: "为您节省了: ¥%.1f元", totalDiscount))


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,837评论 18 139
  • 1.项目经验 2.基础问题 3.指南认识 4.解决思路 ios开发三大块: 1.Oc基础 2.CocoaTouch...
    阳光的大男孩儿阅读 5,016评论 0 13
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 3,865评论 1 10
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,757评论 0 9
  • 在工作,恋爱,以及种种方面我们总会处于被动的局面中。矛盾与焦虑也会随之产生。这个时候你要如何去做? 当上司要求你加...
    城中听雨阅读 915评论 4 6