{"id":1897,"date":"2019-05-19T07:59:17","date_gmt":"2019-05-19T07:59:17","guid":{"rendered":"http:\/\/demensdeum.com\/blog\/?p=1897"},"modified":"2024-12-16T22:32:38","modified_gmt":"2024-12-16T19:32:38","slug":"strategy-pattern","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/pt\/2019\/05\/19\/strategy-pattern\/","title":{"rendered":"Strategy pattern"},"content":{"rendered":"<p>The Strategy pattern allows you to select the type of algorithm that implements a common interface, right while the application is running. This pattern refers to the behavioral design patterns.<\/p>\n<figure id=\"attachment_1899\" aria-describedby=\"caption-attachment-1899\" style=\"width: 366px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/commons.wikimedia.org\/wiki\/File:Enchoen27n3200.jpg\" target=\"_blank\" rel=\"noopener noreferrer\"><img loading=\"lazy\" decoding=\"async\" class=\" wp-image-1899\" src=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2019\/04\/suntzu.jpg\" alt=\"\" width=\"366\" height=\"550\" \/><\/a><figcaption id=\"caption-attachment-1899\" class=\"wp-caption-text\"><a href=\"https:\/\/commons.wikimedia.org\/wiki\/File:Enchoen27n3200.jpg\" target=\"_blank\" rel=\"noopener noreferrer\">Sun Tzu<\/a><\/figcaption><\/figure>\n<p>Suppose we are developing a music player with embedded codecs. The built-in codecs imply reading music formats without using external sources of the operating system (codecs), the player should be able to read tracks of different formats and play them. VLC player has such capabilities, it supports various types of video and audio formats, it runs on popular and not very operating systems.<\/p>\n<p>Imagine what a naive player implementation looks like:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008800; font-weight: bold;\">var<\/span> player: MusicPlayer?\r\n\r\nfunc <span style=\"color: #0066bb; font-weight: bold;\">play<\/span>(filePath: String) {\r\n    let extension = filePath.pathExtension\r\n\r\n    <span style=\"color: #008800; font-weight: bold;\">if<\/span> extension == <span style=\"background-color: #fff0f0;\">\"mp3\"<\/span> {\r\n        playMp3(filePath)\r\n    }\r\n    <span style=\"color: #008800; font-weight: bold;\">else<\/span> <span style=\"color: #008800; font-weight: bold;\">if<\/span> extension == <span style=\"background-color: #fff0f0;\">\"ogg\"<\/span> {\r\n        playOgg(filePath)\r\n    }\r\n}\r\n\r\nfunc <span style=\"color: #0066bb; font-weight: bold;\">playMp3<\/span>(_ filePath: String) {\r\n    player = MpegPlayer()\r\n    player?.playMp3(filePath)\r\n}\r\n\r\nfunc <span style=\"color: #0066bb; font-weight: bold;\">playOgg<\/span>(_ filePath: String) {\r\n    player = VorbisPlayer()\r\n    player?.playMusic(filePath)\r\n}\r\n<\/pre>\n<\/div>\n<p><span class=\"tlid-translation translation\" lang=\"en\"><span class=\"\" title=\"\">Next, we add several formats, which leads to the need to write additional methods.<\/span> <span class=\"\" title=\"\">Plus, the player must support plug-in libraries, with new audio formats that will appear later.<\/span> <span class=\"\" title=\"\">There is a need to switch the music playback algorithm, the Strategy pattern is used to solve this problem.<\/span><\/span><\/p>\n<p><span class=\"tlid-translation translation\" lang=\"en\"><span class=\"\" title=\"\">Let&#8217;s create a common protocol MusicPlayerCodecAlgorithm, write the implementation of the protocol in two classes MpegMusicPlayerCodecAlgorithm and VorbisMusicPlayerCodecAlgorithm, to play mp3 and ogg files with-but.<\/span> <span class=\"\" title=\"\">Create a class MusicPlayer, which will contain a reference for the algorithm that needs to be switched, then by the file extension we implement codec type switching:<\/span><\/span><\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; border: solid gray; border-width: .1em .1em .1em .8em; padding: .2em .6em;\">\n<pre style=\"margin: 0; line-height: 125%;\">import Foundation\r\n\r\n<span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">MusicPlayer<\/span> {\r\n    <span style=\"color: #008800; font-weight: bold;\">var<\/span> playerCodecAlgorithm: MusicPlayerCodecAlgorithm?\r\n    \r\n\tfunc <span style=\"color: #0066bb; font-weight: bold;\">play<\/span>(_ filePath: String) {\r\n            playerCodecAlgorithm?.play(filePath)\r\n\t}\r\n}\r\n\r\nprotocol MusicPlayerCodecAlgorithm {\r\n    func <span style=\"color: #0066bb; font-weight: bold;\">play<\/span>(_ filePath: String)\r\n}\r\n\r\n<span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">MpegMusicPlayerCodecAlgorithm<\/span>: MusicPlayerCodecAlgorithm {\r\n\tfunc <span style=\"color: #0066bb; font-weight: bold;\">play<\/span>(_ filePath: String) {\r\n\t\tdebugPrint(<span style=\"background-color: #fff0f0;\">\"mpeg codec - play\"<\/span>)\r\n\t}\r\n}\r\n\r\n<span style=\"color: #008800; font-weight: bold;\">class<\/span> <span style=\"color: #bb0066; font-weight: bold;\">VorbisMusicPlayerCodecAlgorithm<\/span>: MusicPlayerCodecAlgorithm {\r\n\tfunc <span style=\"color: #0066bb; font-weight: bold;\">play<\/span>(_ filePath: String) {\r\n\t\tdebugPrint(<span style=\"background-color: #fff0f0;\">\"vorbis codec - play\"<\/span>)\t\r\n\t}\r\n}\r\n\r\nfunc <span style=\"color: #0066bb; font-weight: bold;\">play<\/span>(fileAtPath path: String) {\r\n\tguard let url = URL(string: path) <span style=\"color: #008800; font-weight: bold;\">else<\/span> { <span style=\"color: #008800; font-weight: bold;\">return<\/span> }\r\n\tlet fileExtension = url.pathExtension\r\n\t\t\r\n\tlet musicPlayer = MusicPlayer()\r\n\t<span style=\"color: #008800; font-weight: bold;\">var<\/span> playerCodecAlgorithm: MusicPlayerCodecAlgorithm? \r\n\t\t\r\n\t<span style=\"color: #008800; font-weight: bold;\">if<\/span> fileExtension == <span style=\"background-color: #fff0f0;\">\"mp3\"<\/span> {\r\n                playerCodecAlgorithm = MpegMusicPlayerCodecAlgorithm()\r\n\t}\r\n\t<span style=\"color: #008800; font-weight: bold;\">else<\/span> <span style=\"color: #008800; font-weight: bold;\">if<\/span> fileExtension == <span style=\"background-color: #fff0f0;\">\"ogg\"<\/span> {\r\n                playerCodecAlgorithm = VorbisMusicPlayerCodecAlgorithm()\r\n\t}\r\n\t\t\r\n\tmusicPlayer.playerCodecAlgorithm = playerCodecAlgorithm\r\n\tmusicPlayer.playerCodecAlgorithm?.play(path)\r\n}\r\n\r\nplay(fileAtPath: <span style=\"background-color: #fff0f0;\">\"Djentuggah.mp3\"<\/span>)\r\nplay(fileAtPath: <span style=\"background-color: #fff0f0;\">\"Procrastinallica.ogg\"<\/span>)\r\n<\/pre>\n<\/div>\n<p><span class=\"tlid-translation translation\" lang=\"en\"><span class=\"\" title=\"\">The above example also shows the simplest example of a factory (switching the codec type from the file extension) It is important to note that the Strategy strategy does not create objects, it only describes how to create a common interface for switching the family of algorithms.<\/span><\/span><\/p>\n<h3>Documentation<\/h3>\n<p><a href=\"https:\/\/refactoring.guru\/en\/design-patterns\/strategy\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/refactoring.guru\/en\/design-patterns\/strategy<\/a><\/p>\n<h3>Source code<\/h3>\n<p><a href=\"https:\/\/gitlab.com\/demensdeum\/patterns\/\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/patterns\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Strategy pattern allows you to select the type of algorithm that implements a common interface, right while the application is running. This pattern refers to the behavioral design patterns. Suppose we are developing a music player with embedded codecs. The built-in codecs imply reading music formats without using external sources of the operating system<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/pt\/2019\/05\/19\/strategy-pattern\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Strategy pattern&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[61,52],"tags":[95,102],"class_list":["post-1897","post","type-post","status-publish","format-standard","hentry","category-techie","category-tutorials","tag-patterns","tag-strategy","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"pt","enabled_languages":["en","ru","zh","de","fr","ja","pt"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":false,"content":false,"excerpt":false},"de":{"title":false,"content":false,"excerpt":false},"fr":{"title":false,"content":false,"excerpt":false},"ja":{"title":false,"content":false,"excerpt":false},"pt":{"title":false,"content":false,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/1897","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=1897"}],"version-history":[{"count":23,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/1897\/revisions"}],"predecessor-version":[{"id":1941,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/1897\/revisions\/1941"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=1897"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=1897"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=1897"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}