侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

实例讲解Ruby使用设计模式中的装饰器模式的方法

技术  /  管理员 发布于 6年前   370

概述
       若你从事过面向对象开发,实现给一个类或对象增加行为,使用继承机制,这是所有面向对象语言的一  个基本特性。如果已经存在的一个类缺少某些方法,或者须要给方法添加更多的功能(魅力),你也许会仅仅继承这个类来产生一个新类―这建立在额外的代码上。
      通过继承一个现有类可以使得子类在拥有自身方法的同时还拥有父类的方法。但是这种方法是静态的,用户不能控制增加行为的方式和时机。如果  你希望改变一个已经初始化的对象的行为,你怎么办?或者,你希望继承许多类的行为,改怎么办?前一个,只能在于运行时完成,后者显然时可能的,但是可能会导致产生大量的不同的类―可怕的事情。
问题
      你如何组织你的代码使其可以容易的添加基本的或者一些很少用到的 特性,而不是直接不额外的代码写在你的类的内部?

解决方案

  •        动态地给一个对象添加一些额外的职责或者行为。就增加功能来说, Decorator模式相比生成子类更为灵活。
  •        提供了改变子类的灵活方案。装饰器模式在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
  •        当用于一组子类时,装饰器模式更加有用。如果你拥有一族子类(从一个父类派生而来),你需要在与子类独立使用情况下添加额外的特性,你可以使用装饰器模式,以避免代码重复和具体子类数量的增加。

 适用性

       以下情况使用Decorator模式

  •       在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  •       处理那些可以撤消的职责。
  •       当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,

      为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。

      另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
 
实例

class SimpleWriter  def initialize(path)   @file = File.open(path,"w")  end    def write_line(line)   @file.print(line)   @file.print("\n")  end    #字符数  def pos   @file.pos  end    #它将会将文件指针指向文件的开头  def rewind   @file.rewind  end    def close   @file.colse  end end   sw = SimpleWriter.new("test.txt") sw.write_line("你好") puts sw.pos puts sw.rewind   #基类 class WriterDecorator  def initialize(real_writer)   @real_writer = real_writer  end    def write_line   @real_writer.write_line  end    def pos   @real_writer.pos  end    def rewind   @real_writer.rewind  end    def close   @real_writer.close  end end   class NumberingWriter < WriterDecorator  attr :line_number  def initialize(real_writer)   super(real_writer)   @line_number = 1  end    #实际调用的是WriterDecorator的write_line方法,只是在写入的内容前加上了编号(装饰)  #所以说NumberingWriter对WriterDecorator的接口wirte_line进行了装饰  #  def write_line(line)   @real_writer.write_line("#{@line_number}:#{line}")   @line_number += 1  end end   sw = SimpleWriter.new("numbering_write.txt") nw = NumberingWriter.new(sw) nw.write_line("hello,world") nw.write_line("hello,ruby") puts nw.line_number   class CheckSummingWriter < WriterDecorator  attr_reader :check_num    def initialize(real_writer)   super(real_writer)   @check_num = 0  end    def write_line(line)   line.each_byte{|byte| @check_num += byte % 256}   @real_writer.write_line(line)  end end   sw = SimpleWriter.new("check_num_writer.txt") csw = CheckSummingWriter.new(sw) csw.write_line("hello,world") puts csw.check_num   class TimeStampingWriter < WriterDecorator    def initialize(real_writer)   super(real_writer)  end    def write_line(line)   @real_writer.write_line("#{Time.now}: #{line}")  end   end   #倒着看 #5. 实际调用的是SimpleWriter得write_line方法,将内容写入文件 sw = SimpleWriter.new("mix.txt") #4. 实际调用的是NumberingWriter得write_line方法,对在输入的数据前加上了编号 #  然后传给@real_writer,此时的@real_witer为sw nw = NumberingWriter.new(sw) #3. 实际调用的是TimeStampingWriter得write_line方法,对在输入的数据前加上了时间戳 #  然后传给@real_writer,此时的@real_witer为nw tsw = TimeStampingWriter.new(nw) #2. 实际调用的是CheckSummingWriter得write_line方法,对输入的数据进行了字节数的统计 #  然后传给@real_writer,此时的@real_witer为tsw csw = CheckSummingWriter.new(tsw) #1. csw调用write_line csw.write_line("hello,world") puts csw.check_num 

两种ruby风格的装饰模式应用
 
(1)使用extend混入模块

class SimpleWriter  def initialize(path)   @file = File.open(path,"w")  end   def write_line(line)   @file.print(line)   @file.print("\n")  end   #字符数  def pos   @file.pos  end   #它将会将文件指针指向文件的开头  def rewind   @file.rewind  end   def close   @file.colse  end end  #使用extend方法动态的混入模块,来进行装饰  module TimeStampingWriter  def write_line(line)   super("#{Time.now}:#{line}")  end end  module NumberingWriter  attr_reader :line_number  def write_line(line)   @line_number = 1 unless @line_number   super("#{@line_number}:#{line}")   @line_number += 1  end end 

 
最后被加入的模块,先被调用,然后通过super来调用父类的write_line方法。 
例子中先在文本的前面加上时间戳,在加入编号,最后写入文件  

sw = SimpleWriter.new("out3.txt") sw.extend(NumberingWriter) sw.extend(TimeStampingWriter) sw.write_line("hello,ruby") 

 
(2)使用alias关键字

class SimpleWriter  def initialize(path)   @file = File.open(path,"w")  end   def write_line(line)   @file.print(line)   @file.print("\n")  end   #字符数  def pos   @file.pos  end   #它将会将文件指针指向文件的开头  def rewind   @file.rewind  end   def close   @file.colse  end end   ruby实现装饰模式的另一种动态方法 : 修改对象的实例方法, 所以在out1.txt文件中会加入时间戳,而不影响对象sw2,out2.txt中不会加入时间戳 。 sw1 = SimpleWriter.new("out1.txt") class << sw1  alias old_write_line write_line  def write_line(line)   old_write_line("#{Time.now}:#{line}")  end end sw1.write_line("hello,world") sw2 = SimpleWriter.new("out2.txt") sw2.write_line("hello,world") 


  • 上一条:
    java比php难吗?
    下一条:
    电脑如何进入BIOS 设置U盘启动
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 智能合约Solidity学习CryptoZombie二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 2024.07.09日OpenAI将终止对中国等国家和地区API服务(0个评论)
    • 2024/6/9最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(1个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2017-09
    • 2018-01
    • 2018-07
    • 2018-08
    • 2018-09
    • 2018-12
    • 2019-01
    • 2019-02
    • 2019-03
    • 2019-04
    • 2019-05
    • 2019-06
    • 2019-07
    • 2019-08
    • 2019-09
    • 2019-10
    • 2019-11
    • 2019-12
    • 2020-01
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-12
    • 2024-02
    • 2024-04
    • 2024-05
    • 2024-06
    • 2025-02
    • 2025-07
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客