移动端访问不佳,请访问我的个人博客

设计模式学习的demo地址,欢迎大家学习交流

装饰模式

在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。

装饰模式的特点

  1. 装饰对象和真实对象有相同的接口。这样客户端对象就能以和真实对象相同的方式和装饰对象交互。
  2. 装饰对象包含一个真实对象的引用(reference)
  3. 装饰对象接受所有来自客户端的请求。它把这些请求转发给真实的对象。
  4. 装饰对象可以在转发这些请求以前或以后增加一些附加功能。这样就确保了在运行时,不用修改给定对象的结构就可以在外部增加附加的功能。在面向对象的设计中,通常是通过继承来实现对给定类的功能扩展。

装饰模式的基本实现

上图是最基本的装饰模式的结构图,下面将用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() {

    }
}

通过以上代码我们就能简单了解装饰模式的基本实现于过程,它的主要的目的就是:在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能,就像以上示例代码一样,通过ConcreteDecoratorAConcreteDecoratorB去扩展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

这样就用装饰模式简单了实现了一下这个过程,在不改变SuvMpv这两个类的源文件的情况下对它进行操作。

总结

我们先看看装饰模式的优点:

  1. 可以将类中装饰功能从类中搬出移除,这样可以简化原有的类
  2. 有效的将核心职责和装饰功能区分开来,而且可以除去相关类中重复的装饰逻辑

装饰模式的缺点:

  1. 装饰模式虽然扩展性较高,类的数量略多,如何取舍可扩展性和简洁性是个问题,有所选择就要有所牺牲
  2. 很难搞清楚一个类究竟被装饰了多少层,可能是1层,也可能是100层

以上是我对于装饰模式的理解,如果有不对的地方欢迎大家交流,最后谢谢大家的阅读~~

swift设计模式学习 - 装饰模式的更多相关文章

  1. swift设计模式学习 - 策略模式

    移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 策略模式 策略模式定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到使用算法的客户. ...

  2. swift设计模式学习 - 代理模式

    移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 代理模式 代理模式为其他对象提供一种代理以控制对这个对象的访问,在某些情况下,一个对象不适合或者不能直接引用另一个对象 ...

  3. swift设计模式学习 - 原型模式

    移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 原型模式 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 定义 用原型实例指定创建对象的种类,并且通 ...

  4. swift设计模式学习 - 模板方法模式

    移动端访问不佳,请访问我的个人博客 设计模式学习的demo地址,欢迎大家学习交流 模板方法模式 模板方法模式,定义一个操作中算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结 ...

  5. Java设计模式学习记录-装饰模式

    前言 装饰模式也是一种结构型模式,主要是目的是相对于类与类之间的继承关系来说,使用装饰模式可以降低耦合度.JDK中有不少地方都使用到了装饰模式,例如Java的各种I/O流,javax.swing包中一 ...

  6. java设计模式之装饰模式

    发现设计模式的学习越来越让自己学习的东西太少了,应该多接触一些东西,多出去走一走. 装饰模式概念: 动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活(大话设计模式) 在不 ...

  7. python之路,Day24 常用设计模式学习

    python之路,Day24 常用设计模式学习   本节内容 设计模式介绍 设计模式分类 设计模式6大原则 1.设计模式介绍 设计模式(Design Patterns) --可复用面向对象软件的基础 ...

  8. Java设计模式学习记录-GoF设计模式概述

    前言 最近要开始学习设计模式了,以前是偶尔会看看设计模式的书或是在网上翻到了某种设计模式,就顺便看看,也没有仔细的学习过.前段时间看完了JVM的知识,然后就想着JVM那么费劲的东西都看完了,说明自己学 ...

  9. Java设计模式学习记录-迭代器模式

    前言 这次要介绍的是迭代器模式,也是一种行为模式.我现在觉得写博客有点应付了,前阵子一天一篇,感觉这样其实有点没理解透彻就写下来了,而且写完后自己也没有多看几遍,上次在面试的时候被问到java中的I/ ...

随机推荐

  1. elasticsearch的store属性 vs _source字段

    众所周知_source字段存储的是索引的原始内容,那store属性的设置是为何呢?es为什么要把store的默认取值设置为no?设置为yes是否是重复的存储呢? 我们将一个field的值写入es中,要 ...

  2. 研究php单例模式实现数据库类

    实现单例模式:单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. 单例模式的逻辑:类里面声明一个静态的方法和变量,静态变量用 ...

  3. JavaScript json和字符串互转

    JavaScript内置json和字符串互转的函数JSON,不需要引入外部组件 JSON.stringify(obj)将JSON转为字符串. JSON.parse(string)将字符串转为JSON格 ...

  4. git 常用文件目录介绍

    生成的RSA公钥与密钥目录: C:\Users\***\.ssh   系统配置文件路径 C:\ProgramData\Git\ C:\Program Files\Git\mingw64\etc   全 ...

  5. js的class属性获取、增加、移除

    2018年4月10日,北京城的第三份工作已经开始,坚信自己在这里能学到很多,加油! 贴代码,昨天回顾了一点js知识: <script> $(function(){ //赋予一个点击事件 $ ...

  6. JavaWeb—Session与Cookie

    概念 会话:指从一个浏览器窗口打开到关闭期间的一系列动作(可简单理解为用户开一个浏览器,点击多个链接,访问服务器多个web资源,然后关闭浏览器). HTTP协议是无状态协议:每次连接(比如同一个网站的 ...

  7. C++学习笔记--友元

    C++控制对类对象私有部分的访问,在外部无法直接访问类的私有或保护成员.通常,公有类方法提供唯一的访问途径.有时这种限制太严格,不适合特定的编程问题.所以C++提供了友元这种形式,通过让函数或类成为类 ...

  8. 编辑器——vscode

    1.编辑器个人工作配置 // 将设置放入此文件中以覆盖默认设置 { "editor.tabSize": 2, "workbench.iconTheme": &q ...

  9. beego——发行部署

    开发模式 通过bee创建的项目,beego默认情况下是开发模式. 我们可以通过如下的方式改变我们的模式: beego.RunMode = "prod" 或者我们在conf/app. ...

  10. Spring-1-E Game(HDU 5011)解题报告及测试数据

    Game Time Limit:1000MS     Memory Limit:65536KB Description Here is a game for two players. The rule ...