【Swift】面向协议编程的实例

最近维护一项目,是基于面向协议编程的。项目结束后,对面向协议编程有了更深刻的认识,特记录下。由于项目涉密问题,不便公开。只能以网络上例子来说明。

需求

项目的需求大致如此:一个动物园里,先来了一群动物(猫,老鹰和鲨鱼),要先把这些动物入系统库(写实现类);过了没有多久,又来进一批动物(海豚,鸵鸟和金鱼),要求新进动物按类目进行分类处理(这里主要强调实现类的变化)。

分析:

对于先进来的三类动物,最简单的实现就是按动物名称实现类。对于后进来的动物,就是在原来基础上进行扩展。强调的是对已有类的扩展。

我们先按面向对象编程实现一下.(毕竟现在面向对象是最普遍的方式)

import UIKit
/*
 先定义一个基类(Animal),该基类有age和gender两个属性;eat和sleep两方法
*/
class Animal {
    var age:Int {
        return 0
    }
    
    var  gender:Bool {
        return false
    }
    
    func eat() {
        print("Animal.. eat..")
    }
    
    func sleep() {
        print("Animal.. sleep..")
    }
}

/*
  然后定义一个Cat类,继承Animal基类,重写Animal的属性和方法,同时有Cat自己的独特Func(catMethod)
 */
class Cat:Animal {
    
    override var age:Int {
        return 10
    }
    
    override var  gender:Bool {
        return true
    }
    
    override func eat() {
        print("Cat.. eat..")
    }
    
    override func sleep() {
        print("Cat.. sleep..")
    }
    
    func catMethod() {
        print("Cat.. catMethod..")
    }
}

//Eagle(老鹰)
class Eagle:Animal {
    
    override var age:Int {
        return 15
    }
    
    override var  gender:Bool {
        return false
    }
    
    override func eat() {
        print("Eagle.. eat..")
    }
    
    override func sleep() {
        print("Eagle.. sleep..")
    }
    
    func eagleMethod() {
        print("Eagle.. eagleMethod..")
    }
}

//Shark
class Shark:Animal {
    
    override var age:Int {
        return 2
    }
    
    override var  gender:Bool {
        return false
    }
    
    override func eat() {
        print("Shark.. eat..")
    }
    
    override func sleep() {
        print("Shark.. sleep..")
    }
    
    func sharkMethod() {
        print("Shark.. sharkMethod..")
    }
}
/*
 至此,实现了开始的三个动物的实现类;然而对于后进来的三个动物,按需求要分类实现。那就是不能在原来实现类上修改了,只能新增加了。 

 新增加三个类目:哺乳动物类(FeedAnimals),鸟类(Birds)和鱼类(Fishs).并且都有自己的方法
*/
class FeedAnimals:Animal {
    func Run() {
        print("FeedAnimals.. Run..")
    }
}

class Birds:Animal {
    func Fly() {
        print("Birds.. Fly..")
    }
}

class Fishs:Animal {
    func Swimming() {
        print("Fishs.. Swimming..")
    }
}

class FeedAnimalsAndBirds:Animal {
    
    func Fly() {
        print("BirdsAndFishd.. Fly..")
    }
    
    func Run() {
        print("BirdsAndFishd.. Run..")
    }
}

class FeedAnimalsAndFish:Animal {
    
    func Run() {
        print("FeedAnimalsAndBirds.. Run..")
    }
    
    func Swimming() {
        print("FeedAnimalsAndBirds.. Swimming..")
    }
}

//海豚属于动物,可以run,也可以swimming,所以继承Animal,FeedAnimals和Fishs
class Dolphin:FeedAnimalsAndFish {
    
    override var age:Int {
        return 3
    }
    
    override var  gender:Bool {
        return false
    }
    
    override func eat() {
        print("Dolphin.. eat..")
    }
    
    override func sleep() {
        print("Dolphin.. sleep..")
    }
    
    override func Run() { //重写FeedAnimals的方法
        print("Dolphin.. Run..")
    }
    
    override func Swimming() { //重写Fish的方法
        print("Dolphin.. Swimming..")
    }
}

//鸵鸟,属于动物,可以run,所以继承Animal,FeedAnimals
class Ostrich:FeedAnimalsAndBirds {
    
    override var age:Int {
        return 3
    }
    
    override var  gender:Bool {
        return false
    }
    
    override func eat() {
        print("Ostrich.. eat..")
    }
    
    override func sleep() {
        print("Ostrich.. sleep..")
    }
    
    override func Run() { //重写FeedAnimals的方法
        print("Ostrich.. Run..")
    }
}

class Goldfish:Fishs {
    
    override var age:Int {
        return 3
    }
    
    override var  gender:Bool {
        return false
    }
    
    override func eat() {
        print("Goldfish.. eat..")
    }
    
    override func sleep() {
        print("Goldfish.. sleep..")
    }
    
    override func Swimming() { //重写Fish的方法
        print("Goldfish.. Swimming..")
    }
}

至此,使用面向对象方式,完成了按类目分类动物的实现方式。

但是完成这个需求,发现:

1.代码多。写了很多代码且又丑又长。

2.代码重复。很多代码都重复写了。

3.很多子类。派生好几个子类。

4.扩展性不好。开始三个类的代码不好改动,稍一改动,就会影响整个类。

改进

有没有更好方式呢?有的,我们试一下面向协议编程方式。

import UIKit
/*
 首先定义一个AnimalProtocol协议,该协议有可选的age和gender属性;也有可选的eat和sleep方法。
 至于可选方式,我这边使用的是 @objc,当然也可以使用extension来实现可选方式。
*/
@objc public Protocol AnimalProtocol {
    
    @objc var age:Int {}
    @objc var gender:Bool {}
    
    @objc func eat() {}
    
    @objc func sleep() {}
}

/*
 生成一个Cat类,并继承AnimalProtocol协议,对于方法也可以可选择的实现
 */
class Cat:AnimalProtocol {
    
    var age:Int {
        return 2
    }
    
    func eat() {
        print("Cat..eat..")
    }
    
    func sleep() {
        print("Cat..sleep..")
    }
}

/*
 生成一个Eagle类,并继承AnimalProtocol协议,可选实现eat和sleep()
 */
class Eagle:AnimalProtocol {
    func eat() {
        print("Eagle..eat..")
    }
    
    func sleep() {
        print("Eagle..sleep..")
    }
}

//Shark,同样是可选实现
class Shark:AnimalProtocol {
    
    var age:Int {
        return 4
    }
    
    func eat() {
        print("Shark..eat..")
    }
    
    func sleep() {
        print("Shark..sleep..")
    }
}

/*
 对于新的类目FeedAnimals,Brids和Fishs,它们的实现方法就是run,fly和Swimming,
 这里就不对类目进行实现,而是对其能力进行实现.分别定义runable,flyable和swimmingable的能力
 */

@objc public Protocol Runable {
    @objc func run() {}
}

@objc public Protocol Flyable {
    @objc func fly() {}
}

@objc public Protocol Swimmingable {
    @objc func swimming() {}
}

/*
  对于新增加的三个动物,就可以分别继承对应的协议了(协议是可以多继承的)
 */

/*
  Dolphin具有Animal的能力,同时具有Run 和Swimming的能力
 */
class Dolphin:AnimalProtocol,Runable,Swimmingable {
    
    var age:Int {
        return 4
    }
    var gender:Bool {
        return false
    }
    
    func eat() {
        print("Dolphin..eat..")
    }
    
    func sleep() {
        print("Dolphin..sleep..")
    }
    
    func run() {
        print("Dolphin..run..")
    }
    
    func swimming() {
        print("Dolphin..swimming..")
    }
}

/*
 Ostrich具有Animal和Run的能力
 */
class Ostrich:AnimalProtocol,Runable {
    func eat() {
        print("Ostrich..eat..")
    }
    
    func sleep() {
        print("Ostrich..sleep..")
    }
    
    func run() {
        print("Ostrich..run..")
    }
}

class Goldfish:AnimalProtocol,Swimmingable {
    
    func eat() {
        print("Goldfish..eat..")
    }
    
    func swimming() {
        print("Goldfish..swimming..")
    }
}

敲完代码,发现面向协议编程确实比面向对象编程好多啦,具体为:

1.代码量少了很多。

2.协议支持多重继承。减少了子类。

3.协议支持可选。减少没有必要实现的方法或属性。

4.扩展性好多了。对于之前以后写好的类,直接继承新的协议接口,就可以新增加功能了,不会影响到原来的方法或属性,满足开闭原则。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员华仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值