swift设计模式学习 - 装饰模式
移动端访问不佳,请访问我的个人博客
设计模式学习的demo地址,欢迎大家学习交流
装饰模式
在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
装饰模式的特点
- 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
- 装饰对象包含一个真实对象的引用(reference)
- 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
- 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。
装饰模式的基本实现

上图是最基本的装饰模式的结构图,下面将用swift代码来实现一个基本装饰模式:
1).先写一个Component接口
protocol Component {
func operation()
}
2).写一个具体的Component对象
class ConcreteComponent: Component {
func operation() {
// 具体操作的实现
}
}
3).写一个装饰抽象类
class Decorator: Component {
var component: Component?
func operation() {
component?.operation()
}
}
4).写具体的装饰对象
// 装饰对象A
class ConcreteDecoratorA: Decorator {
private var addedState: String?
override func operation() {
super.operation()
addedState = "ConcreteDecoratorA独有的功能,用来区分ConcreteDecoratorB"
// 具体装饰对象A的操作
}
}
// 装饰对象B
class ConcreteDecoratorB: Decorator {
override func operation() {
super.operation()
addedBehavior()
// 具体装饰对象B的操作
}
// ConcreteDecoratorB独有的方法,用来区分ConcreteDecoratorA
private func addedBehavior() {
}
}
通过以上代码我们就能简单了解装饰模式的基本实现于过程,它的主要的目的就是:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能,就像以上示例代码一样,通过ConcreteDecoratorA与ConcreteDecoratorB去扩展ConcreteComponent这个对象的功能,这样不用去改变ConcreteComponent这个类的源文件,也可以达到扩展的效果。
用装饰模式解决实际问题(买车选配的问题)
下面通过一个实际的例子来看看,比如我们在买车的时候一般会选配很多配件,下面我们通过策略模式来实现这一过程,下上个结构图:

下面贴上代码:
// Component
protocol Car {
// 多少钱
func howMuch()-> Int
// 展示装配的配件
func showParts()
}
// ConcreteComponents
class Suv: Car {
init(owner: String) {
print("\(owner)买了一辆Suv,10W")
}
func howMuch() -> Int {
return 10
}
func showParts() {}
}
class Mpv: Car {
init(owner: String) {
print("\(owner)买了一辆Mpv,15W")
}
func howMuch() -> Int {
return 15
}
func showParts() {}
}
// Decorator
class CarParts: Car {
var car: Car?
func howMuch() -> Int {
return car?.howMuch() ?? 0
}
func showParts() {
car?.showParts()
}
func decorator(_ car: Car) -> Car {
self.car = car
return self
}
}
// ConcreteDecorators
class Sofa: CarParts {
override func howMuch() -> Int {
return super.howMuch() + 1
}
override func showParts() {
super.showParts()
print("选配了真皮沙发,1W")
}
}
class Safety: CarParts {
override func howMuch() -> Int {
return super.howMuch() + 3
}
override func showParts() {
super.showParts()
print("选配了全套安全系统,3W")
}
}
class Engine: CarParts {
override func howMuch() -> Int {
return super.howMuch() + 5
}
override func showParts() {
super.showParts()
print("选配了V8发动机,5W")
}
}
下面我们使用一下以上代码看看:
//wcl买一辆suv
var suv: Car = Suv(owner: "wcl")
//装配沙发
suv = Sofa().decorator(suv)
//装配发动机
suv = Engine().decorator(suv)
//装配安全系统
suv = Safety().decorator(suv)
suv.showParts()
print("一共花了\(suv.howMuch())W")
print("\n")
//wcl买一辆mpv
var mpv: Car = Mpv(owner: "wcl")
//装配发动机
mpv = Engine().decorator(mpv)
//装配安全系统
mpv = Safety().decorator(mpv)
mpv.showParts()
print("一共花了\(mpv.howMuch())W")
以下是代码打印的结果:
wcl买了一辆Suv,10W
选配了真皮沙发,1W
选配了V8发动机,5W
选配了全套安全系统,3W
一共花了19W
wcl买了一辆Mpv,15W
选配了V8发动机,5W
选配了全套安全系统,3W
一共花了23W
这样就用装饰模式简单了实现了一下这个过程,在不改变Suv于Mpv这两个类的源文件的情况下对它进行操作。
总结
我们先看看装饰模式的优点:
- 可以将类中装饰功能从类中搬出移除,这样可以简化原有的类
- 有效的将核心职责和装饰功能区分开来,而且可以除去相关类中重复的装饰逻辑
装饰模式的缺点:
- 装饰模式虽然扩展性较高,类的数量略多,如何取舍可扩展性和简洁性是个问题,有所选择就要有所牺牲
- 很难搞清楚一个类究竟被装饰了多少层,可能是1层,也可能是100层
以上是我对于装饰模式的理解,如果有不对的地方欢迎大家交流,最后谢谢大家的阅读~~
swift设计模式学习 - 装饰模式的更多相关文章
- swift设计模式学习 - 策略模式
移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 策略模式 策略模式定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. ...
- swift设计模式学习 - 代理模式
移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 代理模式 代理模式为其他对象提供一种代理以控制对这个对象的访问,在某些情况下,一个对象不适合或者不能直接引用另一个对象 ...
- swift设计模式学习 - 原型模式
移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 原型模式 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 定义 用原型实例指定创建对象的种类,并且通 ...
- swift设计模式学习 - 模板方法模式
移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 模板方法模式 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结 ...
- Java设计模式学习记录-装饰模式
前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一 ...
- java设计模式之装饰模式
发现设计模式的学习越来越让自己学习的东西太少了,应该多接触一些东西,多出去走一走. 装饰模式概念: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活(大话设计模式) 在不 ...
- python之路,Day24 常用设计模式学习
python之路,Day24 常用设计模式学习 本节内容 设计模式介绍 设计模式分类 设计模式6大原则 1.设计模式介绍 设计模式(Design Patterns) --可复用面向对象软件的基础 ...
- Java设计模式学习记录-GoF设计模式概述
前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...
- Java设计模式学习记录-迭代器模式
前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...
随机推荐
- Python全栈day20(装饰器基本理论)
一,什么是装饰器 装饰器:本质就是函数,功能是为其他函数添加附加功能 原则 1,不修改被修饰函数的源代码 2,不修改被修饰函数的调用方式 举例说明:有一个求和函数要求就算出函数的运行时间 正常代码应该 ...
- 网络模型一般是指 OSI 七层参考模型和 TCP/IP 五层参考模型。
网络模型一般是指 OSI 七层参考模型和 TCP/IP 五层参考模型. 每一层实现各自的功能和协议,并且都为上一层提供业务功能.为了提供这 种业务功能,下一层将上一层中的数据并入到本层的数据域中,然后 ...
- 使用maven为web工程引入jstl包时报错了
原pom文件: <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</a ...
- wordpress 自己制作子主题 child theme
使用 WordPress 的子主题(Child Themes)功能快速制作自己的主题 在了解子主题功能之前,先来看一下你在使用 WordPress 的时候是否是这样:不会自己制作主题,只好从网上下载一 ...
- mysql的相关信息
mysql数据库优化技巧 表的设计合理(字段合理,符合3NF) 添加适当索引(index)[主要4种:普通索引,主键索引,唯一索引unique,全文索引] 分表技术(水平分表->拆分表结构,垂直 ...
- Jquery源码分析(一)
版本: jQuery JavaScript Library v3.2.1 分析架构: 打开jquery.js,哇塞,一万多行,噩梦啊!很多人就say bye-bye了.其实,将代码结构拆分后,再分析源 ...
- libevent基础知识
在线手册 • 官方网站:http://libevent.org/ • 官方手册:http://www.wangafu.net/~nickm/libevent-book/ • 官方下载:http://s ...
- Linux系统——VMware克隆
克隆VMware 1. 关闭防火墙 2. 关闭selinux 3. 删除UUID和Mac地址 4.清空网卡缓存 5.关机 ===================== 关闭防火墙 #service ip ...
- SQL Server OBJECTPROPERTY使用方法
OBJECTPROPERTY 返回有关当前数据库中的模式作用域对象的信息.此函数不能用于不是模式范围的对象,例如数据定义语言(DDL)触发器和事件通知. OBJECTPROPERTY 语法: OBJE ...
- MyBatisPartA
(正在补充) 1.从第一个程序开始,通过mybatis实现数据库表内容的增删改查 (源码zip包) 1.0准备工作 建数据库mybatis,在其中创建表sql语句如下: ; -- ---------- ...