V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
matrix67

知名视频下载工具 annie 的一个大重构挺有意思。

  •  
  •   matrix67 · Sep 30, 2020 · 4077 views
    This topic created in 2048 days ago, the information mentioned may be changed or developed.

    annie 是一个视频下载工具。能够下各个视频网站的视频到本地。

    然后之前它下载,都是在 main 函数里面根据 url 进行判断,然后每个包自己实现 Extract 方法。具体为有一个 download 函数

    func download(videoURL string) error {
    	var (
    		domain string
    		err    error
    		data   []downloader.Data
    	)
    ……
    	switch domain {
    	case "douyin", "iesdouyin":
    		data, err = douyin.Extract(videoURL)
    	case "bilibili":
    		data, err = bilibili.Extract(videoURL)
    	case "bcy":
    		data, err = bcy.Extract(videoURL)
    	case "pixivision":
    		data, err = pixivision.Extract(videoURL)
    	case "youku":
    		data, err = youku.Extract(videoURL)
    很多这边就不贴了
     ……
    
    }
    

    最近有个更新,commit 为 424f8def refactor the whole structure (#676), 作者重构了一下,引入了 interface 。具体实现为:

    var extractorMap map[string]types.Extractor
    
    func init() {
    	douyinExtractor := douyin.New()
    	youtubeExtractor := youtube.New()
    
    	extractorMap = map[string]types.Extractor{
    		"": universal.New(), // universal extractor
    
    		"douyin":     douyinExtractor,
    		"iesdouyin":  douyinExtractor,
    		"bilibili":   bilibili.New(),
    		"bcy":        bcy.New(),
    		"pixivision": pixivision.New(),
    		"youku":      youku.New(),
    		"youtube":    youtubeExtractor,
    		"youtu":      youtubeExtractor, // youtu.be
    	……
    	}
    }
    

    然后 extract 里面

    extractor := extractorMap[domain]
    videos, err := extractor.Extract(u, option)
    

    每个包实现了Extractor接口 Extract 方法。

    // Extractor implements video data extraction related operations.
    type Extractor interface {
    	// Extract is the main function to extract the data.
    	Extract(url string, option Options) ([]*Data, error)
    }
    

    这个重构还是挺有意思,作者应该早就想改了,但是是一个大工程,不知道作者心路历程是咋样滴 。

    我想问问 extractorMap[domain] 这个用法是比较 native 的吗。另外好像仅仅针对这个问题,用接口的方法没太省事儿,因为 Extractor 就一个方法,之前的那种写法也可行。感觉就是解耦跟好了?

    下面是之前学习看视频的时候说用接口的好处。 qr.png

    16 replies    2020-10-01 23:12:43 +08:00
    6IbA2bj5ip3tK49j
        1
    6IbA2bj5ip3tK49j  
       Sep 30, 2020
    同样新增一个视频网站下载器
    第一种,理论上需要修改 download 方法。
    第二种,只需要在这个下载器初始化的时候,注册到 extractorMap 中就完事了。
    第二种 1 是把下载和其他逻辑分离开来了。2 是利于拓展。

    总之就是很常见的模式,具体叫啥名忘记了……
    lijialong1313
        2
    lijialong1313  
       Sep 30, 2020
    @xgfan 工厂模式吧……
    lazyfighter
        3
    lazyfighter  
       Sep 30, 2020
    我记得之前看文章写的就是这种,当你的分支足够多的时候就可以抽象出 Map<String,Executor>来搞,最近那个 cola 框架底层我记得就是这种设计,根据不同的场景调用不同的 Executor
    zxlzy
        4
    zxlzy  
       Sep 30, 2020
    这个是非常常见的设计了。。
    zhangshaohan
        5
    zhangshaohan  
       Sep 30, 2020
    看了一下,他支持的网站挺多的,有没有人试过下载的下来么? https://imgchr.com/i/0u3qde
    smilekung
        6
    smilekung  
       Sep 30, 2020
    这不就是策略模式
    matrix67
        7
    matrix67  
    OP
       Sep 30, 2020
    @Geekerstar #5 华生。。。
    @zxlzy #4 嗯嗯是的。go 里面我还第一次见。学习一下。
    @lazyfighter #3 这个我再 py 里面看到过很多。
    guonaihong
        8
    guonaihong  
       Sep 30, 2020
    需要动态选择插件的时候一般都是这么做的。以前在 c 里面做音频编解码,就是用字符串选择编解码器,达到动态桥接的效果。
    WilliamYang
        9
    WilliamYang  
       Sep 30, 2020 via iPhone   ❤️ 1
    就是策略模式,我天天用
    qiumaoyuan
        10
    qiumaoyuan  
       Sep 30, 2020
    没有消除重复的模式没有意义。
    matrix67
        11
    matrix67  
    OP
       Sep 30, 2020
    @WilliamYang 查了下感觉更偏向工厂模式。
    mxalbert1996
        12
    mxalbert1996  
       Sep 30, 2020 via Android
    @lijialong1313 @matrix67
    这明显不是工厂模式,都不实例化叫什么工厂模式。
    reus
        13
    reus  
       Oct 1, 2020 via Android
    就一个 map,也能叫模式?
    太常见的用法了
    lijialong1313
        14
    lijialong1313  
       Oct 1, 2020
    @mxalbert1996 个人觉得的话,如果我要做类似这样一个东西,我会做的像工厂模式。每一个策略,在下载时会实例化一个对象,这样对不同的下载任务就可以不同的管理。
    lxilu
        15
    lxilu  
       Oct 1, 2020 via iPhone
    很自然的做法,谈不上设计模式
    @mxalbert1996 .New() 好像是实例化?
    mxalbert1996
        16
    mxalbert1996  
       Oct 1, 2020 via Android
    @lxilu 工厂模式指的是工厂根据客户需求生产类的实例后交付客户,你见过哪个工厂从头到尾只生产一个实例还一直留着每来一个客户就借他用一下的?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1025 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 53ms · UTC 18:30 · PVG 02:30 · LAX 11:30 · JFK 14:30
    ♥ Do have faith in what you're doing.