MY_OC_你好, 设计模式

你好, 设计模式

  • 滴水可以穿石 百炼才能成钢,谋全局而通一域 致广大而尽精微

初步学习设计模式

设计模式使用的场景

  • 设计模式是为特定场景下的问题定制的解决方案.
  • 特定场景指的是: 问题所在重复出现的场景

设计模式的原则

  • 构建可复用/可维护的面向对象应用程序原则.
  • 比如”优先使用对象组合而不是类继承”和”针对街口编程而不是针对实现编程”

设计模式的作用

  • 程序将因此能够更灵活可靠地进行变更, 因为我们消除了部分与部分之间的依赖关系并减少了耦合.

1. 针对接口编程, 而不是针对实现编程

2. 优先使用对象组合而不是类继承

使用类继承和对象组合的白箱和黑箱复用各有其优缺点. 以下是对类继承的一些优缺点的总结.
继承实现: “白箱复用”
优点是:
- 类继承简单直接, 因为关系在静态编译时静态定义
- 被复用的实现易于修改
缺点是:
- 因为类继承在编译时定义, 所以无法在运行时变更从父类继承来的实现
- 子类的部分描述常常定义在父类中
- 子类直接面对父类的实现的细节, 因此破坏了封装
- 父类实现的任何变更都会强制子类也进行变更, 因为他们的实现联系在了一起
- 因为在新的场景下继承来的实现已经过时或不适用, 所以必须重写父类或继承来的实现

类对象组合被称为: “黑箱复用”
优点是:
- 不会破坏封装, 因为只通过接口来访问对象
- 大大减少实现的依存关系, 因为对象的实现是通过接口来定义的
- 可以在运行时将任意对象替换为其他同类型的对象
- 有助于保持类的封装以专注于单一任务
- 类及层次结构能保持简洁, 不至于过度膨胀无法管理

缺点是:
- 设计中涉及较多对象
- 系统的行为将依赖于不同对象间的关系, 而不是定义于单个类中
- 理想情况下, 不需要创建新的组件就能实现复用, 十分罕见的情况是, 通过对象组合的方式, 仅仅对已有的组件进行组合就能得到所需的全部功能, 实际上, 现成的组件总是不太够用.

如何使用:

优先使用对象组合而不是类继承, 并不是说完全不使用类继承. 需要根据具体情况对如何复用类和对象做出清晰的判断. 如果系统设计的合理, 类继承与对象组合可以相互配合. 设计类时, 通常倾向于考虑对象组合. 然后寻出冗余行为,进行设计细化. 如果找到荣誉行为, 也就意味着此处应该使用类继承.

类图 组合关系

1. 协议 抽象类 具体类 和 范畴
2.实例化
3. 继承
OC中是通过isa指针实现继承的
4. 相识 @class
acquaintance 
这种关系与另一种叫做聚合的关系对于对象组合原则至关重要(聚合将在后面讨论). 
A拥有对B对象的引用, 但不拥有B对象的实体, 而且引用也可以被其他对象分享. 简单的说, A认识B
5. 聚合
6. 伪代码
7. 对象图

涉及21种设计模式

根据其实际主题或应用领域分为以下8个功能部分: 对象创建 接口适应 对象去耦合 抽象集合 行为扩展 算法封装 性能与对象访问 以及对象状态

【创建型模式一】简单工厂(Simple Factory)

【创建型模式二】工厂方法(Factory Method)

【创建型模式三】抽象工厂(Abstract Factory)

【创建型模式四】单例模式(Singleton)

【创建型模式五】生成器(Builder)

【创建型模式六】原型模式(Prototype)

【结构型模式七】外观模式(Facade)

【结构型模式八】适配器(Adapter)

【结构型模式九】桥接模式(Bridge)

【结构型模式十】组合模式(Composite)

【结构型模式十一】装饰者(Decorator)

【结构型模式十二】享元模式(Flyweight)

【结构型模式十三】代理模式(Proxy)

【行为型模式十四】责任链模式(Chain of Responsibility)

【行为型模式十五】策略模式(Strategy)

【行为型模式十六】模板方法模式(Template Method)

【行为型模式十七】命令模式-1(Command)

【行为型模式十八】观察者模式(Observer)

【行为型模式十九】访问者模式(Visitor)

【行为型模式二十】状态模式-1(State)

【行为型模式二十一】解释器模式(Interpreter)

【行为型模式二十二】迭代器模式(Iterator)

【行为型模式二十三】中介者模式(Mediator)

【行为型模式二十四】备忘录模式(Memento)

【创建型模式一】简单工厂(Simple Factory)

【创建型模式二】工厂方法(Factory Method)

以”类族模式”隐藏实现细节
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推到子类

工厂方法模式的应用范围:

  • 编译时无法确定要创建的类得对象
  • 类想让子类在运行时创建什么
  • 类有若干辅助类子类,想要返回哪个子类这一信息局部化

工厂方法是面向对象软件设计中应用非常普遍的设计模式, 工厂方法从代码中消除了对应用程序持有类的耦合, 代码只需处理接口, 所以同一代码得以复用.

【创建型模式三】抽象工厂(Abstract Factory)

抽象工厂模式常与原型模式、单例模式、享元模式等其他设计模式一起使用

抽象工厂: 提供一个创建一系列相关或相互依赖对象的接口, 而无需指定他们具体的类
(<设计模式> addison-wesley)

抽象工厂与工厂方法对比:

抽象工厂:

  1. 通过对象组合创建抽象产品
  2. 创建多系列产品
  3. 必须修改父类的接口才能支持新的产品

工厂方法:
1. 通过继承类创建抽象产品
2. 创建一种产品
3. 子类化创建者并重载工厂方法以创建新产品

软件设计的黄金法则:

变动需要抽象

总结

抽象工厂模式是一种极为常见的设计模式, 他是最基本的, 因为它可以涉及许多类型的对象创建. 一系列相关类的好的模式, 应该作为一种抽象, 不为客户端所见. 抽象工厂可以顺畅的提供这种抽象, 而不暴露创建过程中任何不必要的细节或所创建的对象确切类型.

【创建型模式四】单例模式(Singleton)

单例模式

保证一个类仅有一个实例, 并提供一个访问它的全局访问点

何时使用单利模式

  • 类只能有一个实例, 而且必须从一个为人熟知的访问点对其进行访问, 比如工厂方法
  • 这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端的代码

【创建型模式五】生成器(Builder)

Directer 与 Builder

生成器模式:

将一个复杂对象的构建与它的表现分离, 使得同样的构建过程可以创建不同的表现

何时使用生成器模式(多用于游戏)

  • 需要创建涉及各种部件的复杂对象. 创建对象的算法应该对立于部件的装配方式. 常见的例子是构建组合对象
  • 构建过程需要以不同的方式( 例如, 部件或表现不同组合 )构建对象

生成器与抽象工厂的区别

生 成 器:
- 构建复杂的对象
- 以多个步骤构建对象
- 以多种方式构建对象
- 在构建过程的最后一步返回产品
- 专注一个特定的产品

抽象工厂

  • 构建简单或复杂对象
  • 以单一步骤构建对象
  • 以单一方式构建对象
  • 立刻返回产品
  • 强调一套产品

现在已有例子的情况下在倒过来看看生成器设计模式本身:

生成器包含两个主要的重要角色:Director(CharacterCreator) 和 Builder(Profession)。
Director知道Builder应该建造什么,一参数向其提供缺少的信息来建造特定产品(Character)。
Builder知道究竟如何在缺少某些特定信息的情况下建造什么。

Builder是一个抽象接口(需要子类化),他有一个buildPart方法,该方法由其子类实现,来构造实际的产品(- (Profession )buildStrength:(NSInteger)strength;)。实体类则有一个getResult方法,向客户端返回构造完毕的Product(@property (nonatomic, strong, readonly) Character character;)。

Director定义了一个construct方法,命令Builder的实例去buildPart。(- (Character )createOrcPlayerWithProfession:(Profession )profession;)

Director和Builder形成一种聚合关系。这一位置Builder是一个组成部分,与Director结合,一是整个模式运转,但同时,Director并不负责Builder的生存期。

【创建型模式六】原型模式(Prototype)

深复制就是开辟新内存实现真正的内存复制, 浅复制, 只复制指针, 堆内存不变. 在我们设计系统时, 有时一些对象需要根据用户操作完成拷贝备份等操作, 这时候, 如果再去按照原来的方法初始化一遍对象就会带来一些不便和问题:

该对象的某些属性是在用户操作过程中产生的, 不能够仅凭一个initXXX方法赋值;
常规赋值太过麻烦, 而且破坏封装.

这时候原型模式的优势便体现出来了。总结下原型模式的使用情况:

  • 需要创建的对象应独立于其类型与创建方式。也就是说我们想要的对象并不能够直接通过初始化函数来创建出来,其创建过程不具有普遍性且复杂。
  • 要实例化类是在运行时决定的。在编写代码的时候并不知道哪种对象会被创建出来,其内部的结构如何复杂(例如:复杂程度取决于用户的操作)。
  • 不想要与产品层次相对应的工厂层次。不通过工厂方法或者抽象工厂来控制产品的创建过程,想要直接复制对象
    不同类的实例间的差异仅是状态的若干组合。因此复制相应数量的原型比手工实例化更加方便。
    类不容易创建,比如每个组件可把其他组件作为子节点的组合对象。复制已有的组合对象并对副本进行修改会更加容易。如果内部结构复杂,不容易重现。
  • 常见的使用场景 : 结构复杂的类型, 例如《编程之道》中提及的Mark类型; 或者是相似类, 结构一致, 但是属性不同.

【结构型模式七】外观模式(Facade)

外观模式定义

为系统中的一组接口提供一个统一的接口, 外观定义一个高层接口, 让子系统更易于实现

何时使用外观模式

在以下两种常见情形下, 会考虑使用这一模式
- 子系统正逐渐变得复杂, 应用模式的过程中演化出许多类. 可以使用外观为这些子系统提供一个较简单的接口.
- 可以使用外观对子系统进行分层, 没个子系统级别有一个外观作为入口点. 让他们通过外观进行通信, 可以简化它们的依赖关系

总结

当程序逐渐变大变复杂时, 会有越来越多小型的类和应用模式中演化出来, 如果没有一种简化的方式来使用这些类, 客户端代码最终将变得越来越大、越来越难以理解, 而且, 维护起来会繁琐无趣. 外观有助于提供一种更为简洁的方式来使用子系统中的这些类, 处理这些子系统类的默认行为的, 可能只是定义在外观中的一个简单的方法, 而不必直接去使用这些类.

【结构型模式八】适配器(Adapter)

适配器模式

将一个类的接口转换成客户希望的另外一个接口. 适配器模式使得原本由于接口不兼容而不能一起工作的哪些类可以一起工作

类适配器于对象适配器对比

  • 只针对单一具体的A类, 把A类是配到Tagert
  • 易于重载A的行为, 因为是通过直接子类化进行的适配
  • 只有一个A对象, 无需额外的指针间接访问A

何时使用适配器模式

  • 已有类的接口与需求不匹配
  • 想要一个可复用的类, 该类能够同可能带有不兼容接口的其他类协作
  • 需要适配一个类的几个不同子类, 可是让每一个子类去子类化一个类适配器又不现实,那么可以使用对象适配器(也叫委托)来适配其父类的接口

OC中的应用

  • 委托
  • block

【结构型模式九】桥接模式(Bridge)

http://blog.csdn.net/cctvzxxz1/article/details/40117521

桥接模式的定义

将抽象部分与它的实现分离, 使他们都可以独立的变化

何时使用桥接模式

在一下情形, 自然会想到使用这一模式:
- 不想再抽象与实现之间形成固定的绑定关系 (这样就能在运行时切换实现)
- 抽象及其实现都可以通过子类化独立进行扩展
- 对抽象的实现修改不影响客户端代码
- 如果每个实现需要额外的子类以细化抽象, 则说明有必要把他们分成两个部分
- 想在带有不同抽象接口的多个对象之间共享一个实现

桥接模式是把一个接口是配到不同接口的一种方式.

【结构型模式十】组合模式(Composite)

组合模式的定义

  • 将对象组合成树形结构以表示 “部分-整体” 的层次结构. 组合使用户对单个对象和组合对象的使用具有一致性.

何时使用组合模式

  • 想获得对象抽象的树形表示(部分-整体层次结构)
  • 想让客户端统一处理组合结构中的所有对象

组合模式使用

  • 组合结构的内部表示不应暴露给客户端, 因此组合模式总是跟迭代器模式一起使用, 以便历组合对象中的每一个项目.

总结

组合模式的主要意图是让树形结构中的每个节点具有相同的抽象接口. 这样整个结构可以作为一个统一的抽象结构使用, 而不暴露其内部表示. 对每个节点(叶节点或组合体)的任何操作, 可以通过协议或抽象结构使用, 而不暴露其内部表示, 对每个节点(叶节点或组合体)的任何操作, 可以通过协议或抽象类中定义相同接口来进行

【结构型模式十一】装饰者(Decorator)

【结构型模式十二】享元模式(Flyweight)

【结构型模式十三】代理模式(Proxy)

【行为型模式十四】责任链模式(Chain of Responsibility)

【行为型模式十五】策略模式(Strategy)

【行为型模式十六】模板方法模式(Template Method)

【行为型模式十七】命令模式-1(Command)

【行为型模式十八】观察者模式(Observer)

观察者模式定义

  • 定义对象间的一种一对多的依赖关系, 当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新

何时使用观察者模式

  • 有两种抽象类型相互依赖. 将他们各自封装在各自的对象中, 就可以对它们单独进行改变和复用.
  • 对一个对象的改变需要同时改变其他对象, 而不知道有多少对象有待改变.
  • 一个对象必须通知其他对象, 而又不需知道其他对象是什么

【行为型模式十九】访问者模式(Visitor)

【行为型模式二十】状态模式-1(State)

【行为型模式二十一】解释器模式(Interpreter)

【行为型模式二十二】迭代器模式(Iterator)

迭代器模式定义

  • 提供一种方法顺序访问一个聚合对象中的各个元素, 而又不需暴露该对象内部的表示

基本上有两种迭代器: 外部迭代器和内部迭代器.
- 外部迭代器让客户直接操作迭代过程, 所以客户端需要知道外部迭代器才能使用.另一种情况是, 集合对象(被迭代的目标对象)在其内部维护并操作一个外部迭代器.
- 提供内部迭代器的典型的集合对象为客户端定义一个接口, 或者从底层集合一次访问一个元素, 或者向每个元素发送消息.

外部迭代器与内部迭代器的区别

  1. 外部迭代器

    • 客户端需要知道外部迭代器才能使用, 但是它为客户端提供了更多的控制
    • 客户端创建并维护外部迭代器
    • 客户端可以使用不同外部迭代器实现多种类型的遍历
  2. 内部迭代器

    • 客户端不需要知道任何外部迭代器, 而是可以通过集合对象的特殊接口, 或者一次访问一个元素, 或者向集合中每个元素发送消息.
    • 集合对象本身创建并维护它的外部迭代器
    • 集合对象可以在不修改客户端代码的情况下, 选择不同的外部迭代器

【行为型模式二十三】中介者模式(Mediator)

场景: 在面向对象软件中, 我们在设计中见过许多这样的场景. 典型的例子是应用程序中的UI元素. 比如有个对话框带有静态文本(label)、列表框(list box)、文本框, 以及几个别的输入框. 当列表框中的一项被选中时, 静态文本会被更新为从列表框选定的值. 或者当用户在文本框输入了新值时, 需要把新的值加到列表框的列表中, 当更多的UI元素参与到这一错综复杂的关系之中时, 情况可能变得难以控制. 元素之间需要彼此了解相互操作. 最终, 会发展到难以复用与维护的地步. 需要有个交通管制员来管理所有的UI交通. 组织各种UI元素在同一语境下进行交互的集中化角色, 简称中介者

中介者模式的定义:

  • 用一个对象来封装一系列对象的交互方式. 中介者使各对象不需要显示的相互引用, 从而使其耦合松散, 而且可以独立的改变他们之间的交互.

何为中介者模式

在以下情形, 自然会考虑使用这一模式:
- 对象间的交互虽定义明确然而非常复杂, 导致一组对象彼此相互依赖而且难以理解.
- 因为对象引用了许多其他对象并与其通讯, 导致了对象难以复用
- 想要定制一个分布在多个类中的逻辑或行为, 又不想生成太多子类.

【行为型模式二十四】备忘录模式(Memento)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值