1, 工厂方法,抽象工厂,简单工厂的区别和联系?
工厂与工厂方法,较简单
工厂方法中,给一些描述信息,返回具体的对象
描述信息,就是传参,说一下啥情况
// 工厂,可以方便的创建对象
public class AnnotationFactory {
// 工厂方法,返回一个具体的对象
public func createBusinessMapViewModel(for business: YLPBusiness) -> BusinessMapViewModel? {
guard let yelpCoordinate = business.location.coordinate else {
return nil
}
let coordinate = CLLocationCoordinate2D(latitude: yelpCoordinate.latitude,
longitude: yelpCoordinate.longitude)
let name = business.name
let rating = business.rating
let image: UIImage
switch rating {
case 3.0..<3.5:
image = UIImage(named: "bad")!
case 3.5..<4.0:
image = UIImage(named: "meh")!
default:
image = UIImage(named: "bad")!
}
return BusinessMapViewModel(coordinate: coordinate,
image: image,
name: name,
rating: rating)
}
}
抽象工厂,更加灵活,包含一组工厂方法。
一般,我们需要一组关联性强的对象时,使用抽象工厂
例子:
工厂 A 和 B, 遵守抽象工厂协议,
( 也可以继承自抽象工厂类 )
具体类工厂 A ( concrete class),提供安卓平台的按钮和图片,
具体类工厂 B ,提供 iOS 平台的按钮和图片,
protocol Btn{
}
protocol Img{
}
struct AndroidBtn: Btn{}
struct AndroidImg: Img{}
struct IOSBtn: Btn{}
struct IOSImg: Img{}
// 抽象工厂
protocol AbstractFactory{
func btn() -> Btn
func img() -> Img
}
// 简单工厂
// single factory
struct AndroidFactory: AbstractFactory{
// 工厂方法
func btn() -> Btn {
return AndroidBtn()
}
func img() -> Img {
return AndroidImg()
}
}
struct IOSFactory: AbstractFactory{
func btn() -> Btn {
return IOSBtn()
}
func img() -> Img {
return IOSImg()
}
}
多产品,多平台,
多场景下,
使用抽象工厂,将代码组织得好一些
( 把创建的对象,搭配好,不会混淆 )
2, 策略模式( Strategy Pattern ),最简单的设计模式
策略模式的精华, 是使用组合,不要继承
使用 has a , 解耦 is a
策略模式,让方法独立于使用者( client )
策略模式, 也是代码重用的一种方式
让代码的粒度,更细
例子一,
从这样,
protocol Person{
func rename()
func doSth()
func eatSth()
}
extension Person{
func rename(){
// 昵称,变一下
}
}
// 比较标准的写固定
struct Student: Person{
func doSth(){
// 读书
}
func eatSth(){
// 甜食
}
}
struct Workman: Person{
func doSth(){
// work
}
func eatSth(){
// 吃香的,喝辣的
}
}
struct Lady: Person{
func doSth(){
// work
}
func eatSth(){
// 甜食
}
}
到这样
protocol Person{
var doHabit: ToDo{get set}
var eatPreference: ToEat{get set}
}
protocol ToDo{
func doSth()
}
protocol ToEat{
func eatSth()
}
struct ReadHabit: ToDo{
func doSth() {
// read
}
}
struct WorkHabit: ToDo{
func doSth() {
// work
}
}
struct SugerPreference: ToEat{
func eatSth() {
// 甜食
}
}
struct PepperPreference: ToEat{
func eatSth() {
// 吃香的,喝辣的
}
}
struct Student: Person{
var doHabit: ToDo = ReadHabit()
var eatPreference: ToEat = SugerPreference()
}
struct Workman: Person{
var doHabit: ToDo = WorkHabit()
var eatPreference: ToEat = PepperPreference()
}
struct Lady: Person{
var doHabit: ToDo = WorkHabit()
var eatPreference: ToEat = SugerPreference()
}
如果添加更多的类型,老者 / 歪果仁,
后一种的写法,更清晰
代码的可重用性,更好
例子二, 苹果的 UIViewController 和 UIView
UIViewController has a UIView
苹果建立了控制器 UIViewController,
苹果没有把 UIViewController 作为一种特殊的 UIView.
这也可以说, MVC
例子 3, 苹果的 CALayer 和 UIView
UIView has a CALayer
UIView 没有直接继承 CALayer
3, 装饰者, Decorator Pattern
改变对象的方法,在 runtime, 不是在 compile time,
改变对象的行为,不修改原来的对象,那么使用原对象的封装对象
装饰者模式,也使用了 has a ( 组合 )
装饰者继承自原对象的类,装饰者还有一个原对象类的属性
例 1: 标准
protocol A{
func show()
}
protocol DocorateA: A{
var a: A{get set}
}
struct AOne: A{
func show() {}
}
struct ATwo: A{
func show() {}
}
struct DocorateAOne: DocorateA{
var a: A
func show(){}
}
struct DocorateATwo: DocorateA{
var a: A
func show(){}
}
let a = AOne()
DocorateATwo(a: a).show()
例 2: 好理解些
protocol Fighter{
func chargeVal() -> Int
}
protocol WeaponLoaded: Fighter{
var person: Fighter{get set}
}
struct Bear: Fighter{
func chargeVal() -> Int{
return 5
}
}
struct WithSword: WeaponLoaded{
var person: Fighter
func chargeVal() -> Int{
return person.chargeVal() + 66
}
}
struct WithArrow: WeaponLoaded{
var person: Fighter
func chargeVal() -> Int{
return person.chargeVal() + 6
}
}
let wong = Fighter()
// 老王带上大宝剑装饰器,战斗力就起来了
WithArrow(person: WithSword(person: wong)).chargeVal()
例 3, 工作中用到的, 即 SnapKit
self.view.addSubview(box)
box.snp.makeConstraints { (make) -> Void in
make.width.height.equalTo(50)
make.center.equalTo(self.view)
}
make.width
返回 ConstraintMakerExtendable
,
make.width.height
也返回 ConstraintMakerExtendable
,
public var height: ConstraintMakerExtendable {
self.description.attributes += .height
return self
}
这种链式调用,有借鉴装饰者模式
4,观察者, Observer Pattern
( 接收者 Observers ) 消息是被动过来的,push 过来的,
不是( 接收者)自己去 pull 来的
消息源 ( Observable ),需要给订阅消息的接受者,主动发消息
Observable 发生了变化,Observers 收到消息 ( notified )
观察者模式,one to many 结构,一个消息源,多个订阅者
- Observable 提供 3 个方法:
// 注册就是持有。Observable 持有一个数组的 Observers
1,addObserver(_) // 注册, register
2, removeObserver(_) // 取消注册 , unregister
3, notifyObserver()
- Observer 的方法
update()
- Observable push 消息,给 Observer
Observable 的 notifyObserver(),
调用注册的 Observer 的 update()
( Observable 拿持有的 Observers 集合,一一调用其 update 方法 )