Pregunta

In C# I use strategy pattern with dictionary like this:

namespace NowListeningParserTool.Classes
{
using System.Collections.Generic;

public class WebsiteDictionary
{
    private readonly Dictionary<string, WebsiteParser> _website = new Dictionary<string, WebsiteParser>();

    public WebsiteDictionary()
    {
        _website.Add("YouTube", new YoutubeWebsiteParser());
        _website.Add("977 Music", new NineNineSevenMusicWebsiteParser());
        _website.Add("Grooveshark", new GroovesharkWebsiteParser());
        _website.Add("Sky.FM", new SkyfmWebsiteParser());
        _website.Add("iHeart", new IheartWebsiteParser());
        _website.Add("Live365", new LiveThreeSixFiveWebsiteParser());
        _website.Add("Pandora", new PandoraWebsiteParser());
        _website.Add("Spotify", new SpotifyWebsiteParser());
    }

    public string GetArtistAndTitle(string website, string browser, string stringToParse)
    {
        return _website[website].GetArtistAndTitle(browser, stringToParse, website);
    }

    public string GetWebsiteLogoUri(string website)
    {
        return _website[website].WebsiteLogoUri;
    }
}
}

WebsiteParser is abstract class.

What would be the syntax for this in JavaScript? For example I have multiple IF statements in JavaScript:

function getWebsite() {
    if (document.URL.indexOf('grooveshark.com') >= 0) return getTrackGrooveshark();
    if (document.URL.indexOf('977music.com') >= 0) return getTrack977Music();
    if (document.URL.indexOf('sky.fm/play') >= 0) return getTrackSkyFm();
    if (document.URL.indexOf('iheart.com') >= 0) return getTrackIHeart();
    if (document.URL.indexOf('live365.com') >= 0) return getTrackLive365();
    if (document.URL.indexOf('youtube.com') >= 0) return getTrackYoutube();
    if (document.URL.indexOf('pandora.com') >= 0) return getTrackPandora();
    if (document.URL.indexOf('spotify.com') >= 0) return getTrackSpotify();
}

...that I really don't like, and would like to use the same approach as I did in C# for eliminating these ugly IFs.

Cheers.

¿Fue útil?

Solución

Perhaps something like this, but I dont have enough details to know if this approach will work or not for you. However, it shows how to use objects as key/value stores.

var fetchingStrategies = {
    'grooveshark.com': function () {
        return 'grooving!';
    },
    'youtube.com': function () {
        return 'youtubing!';
    }
};

//execute fetching strategy based on domain
fetchingStrategies['youtube.com']();

Obviously you can replace the hard-coded 'youtube.com' string by a variable that would hold the correct domain for the lookup.

Otros consejos

Option 1: Returns the content from the executed function.

function getWebsite() {
    var websites = [
            ['grooveshark.com',getTrackGrooveshark],
            ['977music.com',getTrack977Music],
            ['sky.fm/play',getTrackSkyFm],
            ['iheart.com',getTrackIHeart],
            ['live365.com',getTrackLive365],
            ['youtube.com',getTrackYoutube],
            ['pandora.com',getTrackPandora],
            ['spotify.com',getTrackSpotify]
        ],
        url = document.URL,
        ret;
    $.each(websites,function(i,v){
        if(url.indexOf(v[0]) !== -1){
           ret = v[1]();
           return false;
        }
    });
    return ret;
}

Option 2: Invoke the function.. Return Nothing

function getWebsite() {
    var websites = [
            ['grooveshark.com',getTrackGrooveshark],
            ['977music.com',getTrack977Music],
            ['sky.fm/play',getTrackSkyFm],
            ['iheart.com',getTrackIHeart],
            ['live365.com',getTrackLive365],
            ['youtube.com',getTrackYoutube],
            ['pandora.com',getTrackPandora],
            ['spotify.com',getTrackSpotify]
        ],
        url = document.URL;

    $.each(websites,function(i,v){
        if(url.indexOf(v[0]) !== -1){
           v[1](); //Executes the function
           return false; //Breaks the Each loop.
        }
    });
}

I think this is really a matter of using a simple JavaScript object. Basically you can reference any property of an object in a similar fashion as you are doing in C#, but I think in a much simpler way. Of course that is my opinion :) I like to structure my modules in a self instantiating manner, like jQuery, so there may be more here than you need in the simplest form. I am also going to assume your parsers are global methods for the example's sake, but you should avoid doing that in real practice. Sorry for any typos as I am doing this in the WYSIWYG editor here.

Here goes:

(function () {

"use strict";

var WebsiteDictionary = function () {

    return new WebsiteDictionary.fn.init();
};

WebsiteDictionary.fn = WebsiteDictionary.prototype = {

    constructor: WebsiteDictionary,

    init: function () {

         this._website["YouTube"] = YoutubeWebsiteParser();
         this._website["977Music"] = NineNineSevenMusicWebsiteParser();
         this._website["Grooveshark"] = GroovesharkWebsiteParser();
         this._website["SkyFM"] = SkyfmWebsiteParser();
         this._website["iHeart"] = IheartWebsiteParser();
         this._website["Live365"] = LiveThreeSixFiveWebsiteParser();
         this._website["Pandora"] = PandoraWebsiteParser();
         this._website["Spotify"] = SpotifyWebsiteParser();

        return this;
    },

   _website: {},


   GetArtistAndTitle: function(website, browser, stringToParse)
   {
      return this._website[website].GetArtistAndTitle(browser, stringToParse, website);
   }

   GetWebsiteLogoUri: function(website)
   {
      return this._website[website].WebsiteLogoUri;
   }


};


// Give the init function the love2DevApp prototype for later instantiation
WebsiteDictionary.fn.init.prototype = WebsiteDictionary.fn;

return (window.WebsiteDictionary= WebsiteDictionary);

}());

I believe this is called an associative array, but don't quote me on that. Basically every member/property of a JavaScript object is accessible in a similar fashion as you access the Dictionary properties in C#. So the member's name is the dictionary key. I also edited the names so they can be valid JavaScript names.

I hope this helps. I think this is a pretty nifty little JavaScript technique. If you review some high profile JavaScript libraries, like jQuery you see this being used a lot.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top