Skip to content

Latest commit

 

History

History
191 lines (132 loc) · 5.39 KB

修饰器模式.md

File metadata and controls

191 lines (132 loc) · 5.39 KB

修饰器模式

上天赋予的生命,就是要为人类的繁荣和平和幸福而奉献。——松下幸之助

定义

本节我们要学习的设计模式叫做一装饰器模式, 何为装饰器模式?假如我们现在有一个视频video需要播放,如果在video播放上加上弹幕,那我们的视频播放还是之前的播放,只不过在原有播放功能上加入了弹幕功能,同样地,我们可以在视频播放上加入3D效果,这样就有了3D播放功能。**这种在原有基础上进行装饰,来添加新的功能的模式 其实就叫做装饰器模式,简称装饰模式。**最直观地就是我们买房后的装修,无非是对原有对象(房子)的一种额外装饰,我们在开头就讲过,软件设计模式其实是从建筑领域延申过来的,这样看来,一点没错。

下面我们列举一个比较简 单的例子,争取以最通俗的语言进行模式的讲解。

使用实例

示例程序的功能是为了给视频播放添加弹幕功能,所谓的弹幕,我们这里比较简单只是单纯的演示使用,就是在原有视频内容的基础.上添加弹幕内容,听起来是不是很炫,其实比较简单,我们一步步来看,首先是我们的示例程序的类图说明:

先来看看抽象类图

具体类图:

实现:

import (
	"fmt"
	"time"
)

媒体播放的接口

type MediaPlayer interface {
	GetMediaName() string
	GetMediaSeconds() int
	GetMediaContent() string
	play()
}

视频的播放类,属于真正被修饰的角色

type VideoPlay struct {
	MediaPlayer
	videoContent string
	videoName string
}

func (v *VideoPlay) GetMediaName() string  {
	return v.videoName
}

func (v *VideoPlay) GetMediaSeconds() int  {
	return len(v.videoContent)
}

func (v *VideoPlay) GetMediaContent() string  {
	return v.videoContent
}

// 模拟媒体播放
func (m *VideoPlay) play() {
	fmt.Println("Media:",m.GetMediaName(),
		"(累计时长:",m.GetMediaSeconds(),"秒)正在播放")
	for i:=0;i<m.GetMediaSeconds();i++ {
		time.Sleep(time.Millisecond)
		fmt.Println("当前播放第",i,"秒"+m.GetMediaContent())
	}
}

弹幕视频播放,定义弹幕播放的角色,具体实现交给子类

type BarrageVideoPlay struct {
	MediaPlayer
}

实现弹幕播放的类,具体的修饰器的实现类

原有的视频播放太过单调,我们现在想在其基础上加入弹幕播放的功能,BarrageVideoPlay抽象类用于定义我们要实现的弹幕播放功能,该类往往只是一个抽象类,内部持有MediaPlay 类的引用,所以其子类可以比较方便的保留使用MediaPlay的既有功能,该类的代码实现如下

// 实现弹幕播放的类,具体的修饰器的实现类
type BarrageRedVideoPlay struct {
	BarrageVideoPlay
}

func (b *BarrageRedVideoPlay) GetMediaName () string {
	return b.MediaPlayer.GetMediaName()+"开启弹幕"
}

func (b *BarrageRedVideoPlay)GetMediaSeconds() int  {
	return b.MediaPlayer.GetMediaSeconds()
}

func (b *BarrageRedVideoPlay)GetMediaContent() string {
	return "弹幕中---"+b.MediaPlayer.GetMediaContent()
}

// 模拟媒体播放
func (m *BarrageRedVideoPlay) play() {
	fmt.Println("Media:",m.GetMediaName(),
		"(累计时长:",m.GetMediaSeconds(),"秒)正在播放")
	for i:=0;i<m.GetMediaSeconds();i++ {
		time.Sleep(time.Millisecond)
		fmt.Println("当前播放第",i,"秒"+m.GetMediaContent())
	}
}

具体调用

mediaplay1 := &VideoPlay{
		videoContent: "射雕英雄传",
		videoName:    "郭靖战欧阳锋",
	}
	mediaplay := &BarrageRedVideoPlay{BarrageVideoPlay{mediaplay1}}
	// 不加修饰时候的播放
	mediaplay1.play()
Media: 郭靖战欧阳锋 (累计时长: 15 秒)正在播放
当前播放第 0 秒射雕英雄传
当前播放第 1 秒射雕英雄传
当前播放第 2 秒射雕英雄传
当前播放第 3 秒射雕英雄传
当前播放第 4 秒射雕英雄传
当前播放第 5 秒射雕英雄传
当前播放第 6 秒射雕英雄传
当前播放第 7 秒射雕英雄传
当前播放第 8 秒射雕英雄传
当前播放第 9 秒射雕英雄传
当前播放第 10 秒射雕英雄传
当前播放第 11 秒射雕英雄传
当前播放第 12 秒射雕英雄传
当前播放第 13 秒射雕英雄传
当前播放第 14 秒射雕英雄传
// 添加修饰后的播放
	mediaplay.play()
Media: 郭靖战欧阳锋开启弹幕 (累计时长: 15 秒)正在播放
当前播放第 0 秒弹幕中---射雕英雄传
当前播放第 1 秒弹幕中---射雕英雄传
当前播放第 2 秒弹幕中---射雕英雄传
当前播放第 3 秒弹幕中---射雕英雄传
当前播放第 4 秒弹幕中---射雕英雄传
当前播放第 5 秒弹幕中---射雕英雄传
当前播放第 6 秒弹幕中---射雕英雄传
当前播放第 7 秒弹幕中---射雕英雄传
当前播放第 8 秒弹幕中---射雕英雄传
当前播放第 9 秒弹幕中---射雕英雄传
当前播放第 10 秒弹幕中---射雕英雄传
当前播放第 11 秒弹幕中---射雕英雄传
当前播放第 12 秒弹幕中---射雕英雄传
当前播放第 13 秒弹幕中---射雕英雄传
当前播放第 14 秒弹幕中---射雕英雄传