[{"data":1,"prerenderedAt":1365},["ShallowReactive",2],{"i-simple-icons:github":3,"i-simple-icons:x":8,"i-brand:linkedin":10,"i-simple-icons:medium":14,"i-lucide:mail":16,"i-lucide:sun":18,"pattern:\u002Flearn\u002Fdesign-patterns\u002Fchain-of-responsibility":20,"pattern-group:\u002Flearn\u002Fdesign-patterns\u002Fchain-of-responsibility":1306,"i-lucide:lightbulb":1343,"i-lucide:workflow":1345,"i-lucide:link":1347,"i-lucide:square-terminal":1349,"i-lucide:list-ordered":1351,"i-lucide:bell":1353,"i-lucide:toggle-left":1355,"i-lucide:shuffle":1357,"i-lucide:layout-template":1359,"i-lucide:footprints":1361,"i-lucide:copy":1363},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M14.234 10.162L22.977 0h-2.072l-7.591 8.824L7.251 0H.258l9.168 13.343L.258 24H2.33l8.016-9.318L16.749 24h6.993zm-2.837 3.299l-.929-1.329L3.076 1.56h3.182l5.965 8.532l.929 1.329l7.754 11.09h-3.182z\"\u002F>",{"left":4,"top":11,"width":12,"height":12,"rotate":4,"vFlip":6,"hFlip":6,"body":13},32,448,"\u003Cpath fill=\"currentColor\" d=\"M416 32L31.9 32C14.3 32 0 46.5 0 64.3L0 447.7C0 465.5 14.3 480 31.9 480L416 480c17.6 0 32-14.5 32-32.3l0-383.4C448 46.5 433.6 32 416 32zM135.4 416l-66.4 0 0-213.8 66.5 0 0 213.8-.1 0zM102.2 96a38.5 38.5 0 1 1 0 77 38.5 38.5 0 1 1 0-77zM384.3 416l-66.4 0 0-104c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9l0 105.8-66.4 0 0-213.8 63.7 0 0 29.2 .9 0c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9l0 117.2z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cpath fill=\"currentColor\" d=\"M4.21 0A4.2 4.2 0 0 0 0 4.21v15.58A4.2 4.2 0 0 0 4.21 24h15.58A4.2 4.2 0 0 0 24 19.79v-1.093a5 5 0 0 1-.422.02c-2.577 0-4.027-2.146-4.09-4.832a8 8 0 0 1 .022-.708c.093-1.186.475-2.241 1.105-3.022a3.9 3.9 0 0 1 1.395-1.1c.468-.237 1.127-.367 1.664-.367h.023q.151 0 .303.01V4.211A4.2 4.2 0 0 0 19.79 0Zm.198 5.583h4.165l3.588 8.435l3.59-8.435h3.864v.146l-.019.004c-.705.16-1.063.397-1.063 1.254h-.003l.003 10.274c.06.676.424.885 1.063 1.03l.02.004v.145h-4.923v-.145l.019-.005c.639-.144.994-.353 1.054-1.03V7.267l-4.745 11.15h-.261L6.15 7.569v9.445c0 .857.358 1.094 1.063 1.253l.02.004v.147H4.405v-.147l.019-.004c.705-.16 1.065-.397 1.065-1.253V6.987c0-.857-.358-1.094-1.064-1.254l-.018-.004zm19.25 3.668c-1.086.023-1.733 1.323-1.813 3.124H24V9.298a1.4 1.4 0 0 0-.342-.047m-1.862 3.632c-.1 1.756.86 3.239 2.204 3.634v-3.634z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":17},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m22 7l-8.991 5.727a2 2 0 0 1-2.009 0L2 7\"\u002F>\u003Crect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":19},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"12\" cy=\"12\" r=\"4\"\u002F>\u003Cpath d=\"M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41\"\u002F>\u003C\u002Fg>",{"id":21,"title":22,"body":23,"description":1292,"example":1293,"extension":1294,"group":1295,"icon":1296,"meta":1297,"navigation":216,"order":177,"path":1298,"rawbody":1299,"seo":1300,"sitemap":1301,"source":1302,"stem":1303,"summary":1304,"__hash__":1305},"patterns\u002Flearn\u002Fdesign-patterns\u002Fchain-of-responsibility.md","Chain of Responsibility",{"type":24,"value":25,"toc":1282},"minimark",[26,31,35,38,41,45,61,65,70,81,85,93,97,100,159,163,395,566,727,992,1184,1190,1198,1214,1272,1278],[27,28,30],"h2",{"id":29},"the-idea","The idea",[32,33,34],"p",{},"A request often needs several checks before it can be served. Is the user signed in? Is their IP address allowed? Have they sent too many requests? Putting all of these checks in one method makes it long, and every new check means editing it.",[32,36,37],{},"The Chain of Responsibility pattern puts each check in its own handler object. Handlers share one interface, and each holds a reference to the next handler. The sender passes the request to the first handler and doesn't know which handler, if any, will deal with it.",[32,39,40],{},"In the Gang of Four version, each handler either handles the request or passes it on. A common variant, used in this example and in web framework middleware, lets every handler run its check and pass the request on, while any handler can stop it.",[27,42,44],{"id":43},"when-to-use-it","When to use it",[46,47,48,52,55,58],"ul",{},[49,50,51],"li",{},"A request has to go through several checks or steps, and you want each one in its own class.",[49,53,54],{},"More than one object may handle a request, and the handler should be chosen at runtime.",[49,56,57],{},"You want to add, remove or reorder steps without changing the sender.",[49,59,60],{},"You are building middleware for web requests, or UI events that move from a control up to its parents.",[27,62,64],{"id":63},"pros-and-cons","Pros and cons",[66,67,69],"h3",{"id":68},"pros","Pros",[46,71,72,75,78],{},[49,73,74],{},"It decouples the sender of a request from the objects that handle it.",[49,76,77],{},"You can change the chain at runtime by adding, removing or reordering handlers.",[49,79,80],{},"Each handler does one job, so it is easy to test on its own.",[66,82,84],{"id":83},"cons","Cons",[46,86,87,90],{},[49,88,89],{},"It can be hard to follow: to know what happens to a request, you have to trace the whole chain.",[49,91,92],{},"A long chain can slow things down, and a request may reach the end without being handled.",[27,94,96],{"id":95},"the-example","The example",[32,98,99],{},"The example checks an incoming web request with three middleware steps: authentication, an IP allow list and throttling. If every step passes, the request is valid.",[46,101,102,124,151],{},[49,103,104,111,112,115,116,119,120,123],{},[105,106,107],"strong",{},[108,109,110],"code",{},"Middleware",": the handler. An abstract class that holds the next handler, sets it with ",[108,113,114],{},"setNextHandler()",", and offers ",[108,117,118],{},"handleNext()",", which passes the request on, or returns ",[108,121,122],{},"true"," at the end of the chain.",[49,125,126,131,132,137,138,143,144,147,148,150],{},[105,127,128],{},[108,129,130],{},"AuthenticateMiddleware",", ",[105,133,134],{},[108,135,136],{},"WhitelistIpMiddleware"," and ",[105,139,140],{},[108,141,142],{},"ThrottlingMiddleware",": concrete handlers. Each prints what it checks, then either returns ",[108,145,146],{},"false"," to stop the request or calls ",[108,149,118],{}," to pass it on. The checks themselves are stubs that always pass.",[49,152,153,158],{},[105,154,155],{},[108,156,157],{},"Demo",": the client. It builds the chain and asks whether the request is valid.",[27,160,162],{"id":161},"the-code","The code",[164,165,171],"pre",{"className":166,"code":167,"filename":168,"language":169,"meta":170,"style":170},"language-java shiki shiki-themes haytham-dark haytham-light","public abstract class Middleware {\n    private Middleware next;\n\n    public Middleware setNextHandler(Middleware next) {\n        this.next = next;\n\n        return next;\n    }\n\n    public abstract boolean handle();\n\n    protected boolean handleNext() {\n        if (next == null) {\n            return true;\n        }\n\n        return next.handle();\n    }\n}\n","Middleware.java","java","",[108,172,173,196,211,218,242,263,268,278,284,289,305,310,326,348,359,365,370,384,389],{"__ignoreMap":170},[174,175,178,182,185,188,192],"span",{"class":176,"line":177},"line",1,[174,179,181],{"class":180},"sVsk0","public",[174,183,184],{"class":180}," abstract",[174,186,187],{"class":180}," class",[174,189,191],{"class":190},"sNwy7"," Middleware",[174,193,195],{"class":194},"sVG6I"," {\n",[174,197,199,202,204,208],{"class":176,"line":198},2,[174,200,201],{"class":180},"    private",[174,203,191],{"class":180},[174,205,207],{"class":206},"sWFPS"," next",[174,209,210],{"class":194},";\n",[174,212,214],{"class":176,"line":213},3,[174,215,217],{"emptyLinePlaceholder":216},true,"\n",[174,219,221,224,226,230,233,235,237,240],{"class":176,"line":220},4,[174,222,223],{"class":180},"    public",[174,225,191],{"class":180},[174,227,229],{"class":228},"sVz7n"," setNextHandler",[174,231,232],{"class":194},"(",[174,234,110],{"class":180},[174,236,207],{"class":206},[174,238,239],{"class":194},")",[174,241,195],{"class":194},[174,243,245,249,252,256,259,261],{"class":176,"line":244},5,[174,246,248],{"class":247},"sheII","        this",[174,250,251],{"class":194},".",[174,253,255],{"class":254},"s4Awn","next",[174,257,258],{"class":194}," =",[174,260,207],{"class":206},[174,262,210],{"class":194},[174,264,266],{"class":176,"line":265},6,[174,267,217],{"emptyLinePlaceholder":216},[174,269,271,274,276],{"class":176,"line":270},7,[174,272,273],{"class":180},"        return",[174,275,207],{"class":206},[174,277,210],{"class":194},[174,279,281],{"class":176,"line":280},8,[174,282,283],{"class":194},"    }\n",[174,285,287],{"class":176,"line":286},9,[174,288,217],{"emptyLinePlaceholder":216},[174,290,292,294,296,299,302],{"class":176,"line":291},10,[174,293,223],{"class":180},[174,295,184],{"class":180},[174,297,298],{"class":180}," boolean",[174,300,301],{"class":228}," handle",[174,303,304],{"class":194},"();\n",[174,306,308],{"class":176,"line":307},11,[174,309,217],{"emptyLinePlaceholder":216},[174,311,313,316,318,321,324],{"class":176,"line":312},12,[174,314,315],{"class":180},"    protected",[174,317,298],{"class":180},[174,319,320],{"class":228}," handleNext",[174,322,323],{"class":194},"()",[174,325,195],{"class":194},[174,327,329,332,335,338,341,344,346],{"class":176,"line":328},13,[174,330,331],{"class":180},"        if",[174,333,334],{"class":194}," (",[174,336,337],{"class":206},"next ",[174,339,340],{"class":194},"==",[174,342,343],{"class":247}," null",[174,345,239],{"class":194},[174,347,195],{"class":194},[174,349,351,354,357],{"class":176,"line":350},14,[174,352,353],{"class":180},"            return",[174,355,356],{"class":247}," true",[174,358,210],{"class":194},[174,360,362],{"class":176,"line":361},15,[174,363,364],{"class":194},"        }\n",[174,366,368],{"class":176,"line":367},16,[174,369,217],{"emptyLinePlaceholder":216},[174,371,373,375,377,379,382],{"class":176,"line":372},17,[174,374,273],{"class":180},[174,376,207],{"class":206},[174,378,251],{"class":194},[174,380,381],{"class":228},"handle",[174,383,304],{"class":194},[174,385,387],{"class":176,"line":386},18,[174,388,283],{"class":194},[174,390,392],{"class":176,"line":391},19,[174,393,394],{"class":194},"}\n",[164,396,399],{"className":166,"code":397,"filename":398,"language":169,"meta":170,"style":170},"public class AuthenticateMiddleware extends Middleware {\n    @Override\n    public boolean handle() {\n        System.out.println(\"check if user is authenticated\");\n\n        if (!checkIfAuthenticated()) {\n            System.out.println(\"User is not authenticated\");\n\n            return false;\n        }\n\n        return handleNext();\n    }\n\n    private boolean checkIfAuthenticated() {\n        return true;\n    }\n}\n","AuthenticateMiddleware.java",[108,400,401,417,425,437,461,465,480,500,504,513,517,521,529,533,537,550,558,562],{"__ignoreMap":170},[174,402,403,405,407,410,413,415],{"class":176,"line":177},[174,404,181],{"class":180},[174,406,187],{"class":180},[174,408,409],{"class":190}," AuthenticateMiddleware",[174,411,412],{"class":180}," extends",[174,414,191],{"class":190},[174,416,195],{"class":194},[174,418,419,422],{"class":176,"line":198},[174,420,421],{"class":194},"    @",[174,423,424],{"class":180},"Override\n",[174,426,427,429,431,433,435],{"class":176,"line":213},[174,428,223],{"class":180},[174,430,298],{"class":180},[174,432,301],{"class":228},[174,434,323],{"class":194},[174,436,195],{"class":194},[174,438,439,442,444,447,449,452,454,458],{"class":176,"line":220},[174,440,441],{"class":206},"        System",[174,443,251],{"class":194},[174,445,446],{"class":254},"out",[174,448,251],{"class":194},[174,450,451],{"class":228},"println",[174,453,232],{"class":194},[174,455,457],{"class":456},"sUOzB","\"check if user is authenticated\"",[174,459,460],{"class":194},");\n",[174,462,463],{"class":176,"line":244},[174,464,217],{"emptyLinePlaceholder":216},[174,466,467,469,472,475,478],{"class":176,"line":265},[174,468,331],{"class":180},[174,470,471],{"class":194}," (!",[174,473,474],{"class":228},"checkIfAuthenticated",[174,476,477],{"class":194},"())",[174,479,195],{"class":194},[174,481,482,485,487,489,491,493,495,498],{"class":176,"line":270},[174,483,484],{"class":206},"            System",[174,486,251],{"class":194},[174,488,446],{"class":254},[174,490,251],{"class":194},[174,492,451],{"class":228},[174,494,232],{"class":194},[174,496,497],{"class":456},"\"User is not authenticated\"",[174,499,460],{"class":194},[174,501,502],{"class":176,"line":280},[174,503,217],{"emptyLinePlaceholder":216},[174,505,506,508,511],{"class":176,"line":286},[174,507,353],{"class":180},[174,509,510],{"class":247}," false",[174,512,210],{"class":194},[174,514,515],{"class":176,"line":291},[174,516,364],{"class":194},[174,518,519],{"class":176,"line":307},[174,520,217],{"emptyLinePlaceholder":216},[174,522,523,525,527],{"class":176,"line":312},[174,524,273],{"class":180},[174,526,320],{"class":228},[174,528,304],{"class":194},[174,530,531],{"class":176,"line":328},[174,532,283],{"class":194},[174,534,535],{"class":176,"line":350},[174,536,217],{"emptyLinePlaceholder":216},[174,538,539,541,543,546,548],{"class":176,"line":361},[174,540,201],{"class":180},[174,542,298],{"class":180},[174,544,545],{"class":228}," checkIfAuthenticated",[174,547,323],{"class":194},[174,549,195],{"class":194},[174,551,552,554,556],{"class":176,"line":367},[174,553,273],{"class":180},[174,555,356],{"class":247},[174,557,210],{"class":194},[174,559,560],{"class":176,"line":372},[174,561,283],{"class":194},[174,563,564],{"class":176,"line":386},[174,565,394],{"class":194},[164,567,570],{"className":166,"code":568,"filename":569,"language":169,"meta":170,"style":170},"public class WhitelistIpMiddleware extends Middleware {\n    @Override\n    public boolean handle() {\n        System.out.println(\"check if ip in database or not\");\n\n        if (!checkIp()) {\n            System.out.println(\"Ip is not in database\");\n            return false;\n        }\n\n        return handleNext();\n    }\n\n    private boolean checkIp() {\n        \u002F\u002F code to check if IP is in database\n        return true;\n    }\n}\n","WhitelistIpMiddleware.java",[108,571,572,587,593,605,624,628,641,660,668,672,676,684,688,692,705,711,719,723],{"__ignoreMap":170},[174,573,574,576,578,581,583,585],{"class":176,"line":177},[174,575,181],{"class":180},[174,577,187],{"class":180},[174,579,580],{"class":190}," WhitelistIpMiddleware",[174,582,412],{"class":180},[174,584,191],{"class":190},[174,586,195],{"class":194},[174,588,589,591],{"class":176,"line":198},[174,590,421],{"class":194},[174,592,424],{"class":180},[174,594,595,597,599,601,603],{"class":176,"line":213},[174,596,223],{"class":180},[174,598,298],{"class":180},[174,600,301],{"class":228},[174,602,323],{"class":194},[174,604,195],{"class":194},[174,606,607,609,611,613,615,617,619,622],{"class":176,"line":220},[174,608,441],{"class":206},[174,610,251],{"class":194},[174,612,446],{"class":254},[174,614,251],{"class":194},[174,616,451],{"class":228},[174,618,232],{"class":194},[174,620,621],{"class":456},"\"check if ip in database or not\"",[174,623,460],{"class":194},[174,625,626],{"class":176,"line":244},[174,627,217],{"emptyLinePlaceholder":216},[174,629,630,632,634,637,639],{"class":176,"line":265},[174,631,331],{"class":180},[174,633,471],{"class":194},[174,635,636],{"class":228},"checkIp",[174,638,477],{"class":194},[174,640,195],{"class":194},[174,642,643,645,647,649,651,653,655,658],{"class":176,"line":270},[174,644,484],{"class":206},[174,646,251],{"class":194},[174,648,446],{"class":254},[174,650,251],{"class":194},[174,652,451],{"class":228},[174,654,232],{"class":194},[174,656,657],{"class":456},"\"Ip is not in database\"",[174,659,460],{"class":194},[174,661,662,664,666],{"class":176,"line":280},[174,663,353],{"class":180},[174,665,510],{"class":247},[174,667,210],{"class":194},[174,669,670],{"class":176,"line":286},[174,671,364],{"class":194},[174,673,674],{"class":176,"line":291},[174,675,217],{"emptyLinePlaceholder":216},[174,677,678,680,682],{"class":176,"line":307},[174,679,273],{"class":180},[174,681,320],{"class":228},[174,683,304],{"class":194},[174,685,686],{"class":176,"line":312},[174,687,283],{"class":194},[174,689,690],{"class":176,"line":328},[174,691,217],{"emptyLinePlaceholder":216},[174,693,694,696,698,701,703],{"class":176,"line":350},[174,695,201],{"class":180},[174,697,298],{"class":180},[174,699,700],{"class":228}," checkIp",[174,702,323],{"class":194},[174,704,195],{"class":194},[174,706,707],{"class":176,"line":361},[174,708,710],{"class":709},"sFjNZ","        \u002F\u002F code to check if IP is in database\n",[174,712,713,715,717],{"class":176,"line":367},[174,714,273],{"class":180},[174,716,356],{"class":247},[174,718,210],{"class":194},[174,720,721],{"class":176,"line":372},[174,722,283],{"class":194},[174,724,725],{"class":176,"line":386},[174,726,394],{"class":194},[164,728,731],{"className":166,"code":729,"filename":730,"language":169,"meta":170,"style":170},"public class ThrottlingMiddleware extends Middleware {\n    private final int requestPerMinute;\n    private final int request;\n\n    public ThrottlingMiddleware(int requestPerMinute, int request) {\n        this.requestPerMinute = requestPerMinute;\n        this.request = request;\n    }\n\n    @Override\n    public boolean handle() {\n        System.out.println(\"handle the functionality for throttling\");\n\n        if (checkThrottling()) {\n            System.out.println(\"Request is throttled\");\n\n            return false;\n        }\n\n        return handleNext();\n    }\n\n    private boolean checkThrottling() {\n        \u002F\u002F code to check if request is throttled\n        return false;\n    }\n}\n","ThrottlingMiddleware.java",[108,732,733,748,763,776,780,804,819,834,838,842,848,860,879,883,896,915,919,927,931,935,944,949,954,968,973,982,987],{"__ignoreMap":170},[174,734,735,737,739,742,744,746],{"class":176,"line":177},[174,736,181],{"class":180},[174,738,187],{"class":180},[174,740,741],{"class":190}," ThrottlingMiddleware",[174,743,412],{"class":180},[174,745,191],{"class":190},[174,747,195],{"class":194},[174,749,750,752,755,758,761],{"class":176,"line":198},[174,751,201],{"class":180},[174,753,754],{"class":180}," final",[174,756,757],{"class":180}," int",[174,759,760],{"class":206}," requestPerMinute",[174,762,210],{"class":194},[174,764,765,767,769,771,774],{"class":176,"line":213},[174,766,201],{"class":180},[174,768,754],{"class":180},[174,770,757],{"class":180},[174,772,773],{"class":206}," request",[174,775,210],{"class":194},[174,777,778],{"class":176,"line":220},[174,779,217],{"emptyLinePlaceholder":216},[174,781,782,784,786,788,791,793,796,798,800,802],{"class":176,"line":244},[174,783,223],{"class":180},[174,785,741],{"class":228},[174,787,232],{"class":194},[174,789,790],{"class":180},"int",[174,792,760],{"class":206},[174,794,795],{"class":194},",",[174,797,757],{"class":180},[174,799,773],{"class":206},[174,801,239],{"class":194},[174,803,195],{"class":194},[174,805,806,808,810,813,815,817],{"class":176,"line":265},[174,807,248],{"class":247},[174,809,251],{"class":194},[174,811,812],{"class":254},"requestPerMinute",[174,814,258],{"class":194},[174,816,760],{"class":206},[174,818,210],{"class":194},[174,820,821,823,825,828,830,832],{"class":176,"line":270},[174,822,248],{"class":247},[174,824,251],{"class":194},[174,826,827],{"class":254},"request",[174,829,258],{"class":194},[174,831,773],{"class":206},[174,833,210],{"class":194},[174,835,836],{"class":176,"line":280},[174,837,283],{"class":194},[174,839,840],{"class":176,"line":286},[174,841,217],{"emptyLinePlaceholder":216},[174,843,844,846],{"class":176,"line":291},[174,845,421],{"class":194},[174,847,424],{"class":180},[174,849,850,852,854,856,858],{"class":176,"line":307},[174,851,223],{"class":180},[174,853,298],{"class":180},[174,855,301],{"class":228},[174,857,323],{"class":194},[174,859,195],{"class":194},[174,861,862,864,866,868,870,872,874,877],{"class":176,"line":312},[174,863,441],{"class":206},[174,865,251],{"class":194},[174,867,446],{"class":254},[174,869,251],{"class":194},[174,871,451],{"class":228},[174,873,232],{"class":194},[174,875,876],{"class":456},"\"handle the functionality for throttling\"",[174,878,460],{"class":194},[174,880,881],{"class":176,"line":328},[174,882,217],{"emptyLinePlaceholder":216},[174,884,885,887,889,892,894],{"class":176,"line":350},[174,886,331],{"class":180},[174,888,334],{"class":194},[174,890,891],{"class":228},"checkThrottling",[174,893,477],{"class":194},[174,895,195],{"class":194},[174,897,898,900,902,904,906,908,910,913],{"class":176,"line":361},[174,899,484],{"class":206},[174,901,251],{"class":194},[174,903,446],{"class":254},[174,905,251],{"class":194},[174,907,451],{"class":228},[174,909,232],{"class":194},[174,911,912],{"class":456},"\"Request is throttled\"",[174,914,460],{"class":194},[174,916,917],{"class":176,"line":367},[174,918,217],{"emptyLinePlaceholder":216},[174,920,921,923,925],{"class":176,"line":372},[174,922,353],{"class":180},[174,924,510],{"class":247},[174,926,210],{"class":194},[174,928,929],{"class":176,"line":386},[174,930,364],{"class":194},[174,932,933],{"class":176,"line":391},[174,934,217],{"emptyLinePlaceholder":216},[174,936,938,940,942],{"class":176,"line":937},20,[174,939,273],{"class":180},[174,941,320],{"class":228},[174,943,304],{"class":194},[174,945,947],{"class":176,"line":946},21,[174,948,283],{"class":194},[174,950,952],{"class":176,"line":951},22,[174,953,217],{"emptyLinePlaceholder":216},[174,955,957,959,961,964,966],{"class":176,"line":956},23,[174,958,201],{"class":180},[174,960,298],{"class":180},[174,962,963],{"class":228}," checkThrottling",[174,965,323],{"class":194},[174,967,195],{"class":194},[174,969,970],{"class":176,"line":5},[174,971,972],{"class":709},"        \u002F\u002F code to check if request is throttled\n",[174,974,976,978,980],{"class":176,"line":975},25,[174,977,273],{"class":180},[174,979,510],{"class":247},[174,981,210],{"class":194},[174,983,985],{"class":176,"line":984},26,[174,986,283],{"class":194},[174,988,990],{"class":176,"line":989},27,[174,991,394],{"class":194},[164,993,996],{"className":166,"code":994,"filename":995,"language":169,"meta":170,"style":170},"public class Demo {\n    public static void main(String[] args) {\n\n        Middleware middleware = new AuthenticateMiddleware()\n                .setNextHandler(new WhitelistIpMiddleware())\n                .setNextHandler(new ThrottlingMiddleware(10, 1));\n\n        if (middleware.handle()) {\n            System.out.println(\"Request is valid\");\n        } else {\n            System.out.println(\"Request is invalid\");\n        }\n    }\n}\n","Demo.java",[108,997,998,1009,1037,1041,1060,1078,1103,1107,1124,1143,1153,1172,1176,1180],{"__ignoreMap":170},[174,999,1000,1002,1004,1007],{"class":176,"line":177},[174,1001,181],{"class":180},[174,1003,187],{"class":180},[174,1005,1006],{"class":190}," Demo",[174,1008,195],{"class":194},[174,1010,1011,1013,1016,1019,1022,1024,1027,1030,1033,1035],{"class":176,"line":198},[174,1012,223],{"class":180},[174,1014,1015],{"class":180}," static",[174,1017,1018],{"class":180}," void",[174,1020,1021],{"class":228}," main",[174,1023,232],{"class":194},[174,1025,1026],{"class":180},"String",[174,1028,1029],{"class":194},"[]",[174,1031,1032],{"class":206}," args",[174,1034,239],{"class":194},[174,1036,195],{"class":194},[174,1038,1039],{"class":176,"line":213},[174,1040,217],{"emptyLinePlaceholder":216},[174,1042,1043,1046,1049,1052,1055,1057],{"class":176,"line":220},[174,1044,1045],{"class":180},"        Middleware",[174,1047,1048],{"class":206}," middleware ",[174,1050,1051],{"class":194},"=",[174,1053,1054],{"class":180}," new",[174,1056,409],{"class":228},[174,1058,1059],{"class":194},"()\n",[174,1061,1062,1065,1068,1070,1073,1075],{"class":176,"line":244},[174,1063,1064],{"class":194},"                .",[174,1066,1067],{"class":228},"setNextHandler",[174,1069,232],{"class":194},[174,1071,1072],{"class":180},"new",[174,1074,580],{"class":228},[174,1076,1077],{"class":194},"())\n",[174,1079,1080,1082,1084,1086,1088,1090,1092,1095,1097,1100],{"class":176,"line":265},[174,1081,1064],{"class":194},[174,1083,1067],{"class":228},[174,1085,232],{"class":194},[174,1087,1072],{"class":180},[174,1089,741],{"class":228},[174,1091,232],{"class":194},[174,1093,1094],{"class":247},"10",[174,1096,795],{"class":194},[174,1098,1099],{"class":247}," 1",[174,1101,1102],{"class":194},"));\n",[174,1104,1105],{"class":176,"line":270},[174,1106,217],{"emptyLinePlaceholder":216},[174,1108,1109,1111,1113,1116,1118,1120,1122],{"class":176,"line":280},[174,1110,331],{"class":180},[174,1112,334],{"class":194},[174,1114,1115],{"class":206},"middleware",[174,1117,251],{"class":194},[174,1119,381],{"class":228},[174,1121,477],{"class":194},[174,1123,195],{"class":194},[174,1125,1126,1128,1130,1132,1134,1136,1138,1141],{"class":176,"line":286},[174,1127,484],{"class":206},[174,1129,251],{"class":194},[174,1131,446],{"class":254},[174,1133,251],{"class":194},[174,1135,451],{"class":228},[174,1137,232],{"class":194},[174,1139,1140],{"class":456},"\"Request is valid\"",[174,1142,460],{"class":194},[174,1144,1145,1148,1151],{"class":176,"line":291},[174,1146,1147],{"class":194},"        }",[174,1149,1150],{"class":180}," else",[174,1152,195],{"class":194},[174,1154,1155,1157,1159,1161,1163,1165,1167,1170],{"class":176,"line":307},[174,1156,484],{"class":206},[174,1158,251],{"class":194},[174,1160,446],{"class":254},[174,1162,251],{"class":194},[174,1164,451],{"class":228},[174,1166,232],{"class":194},[174,1168,1169],{"class":456},"\"Request is invalid\"",[174,1171,460],{"class":194},[174,1173,1174],{"class":176,"line":312},[174,1175,364],{"class":194},[174,1177,1178],{"class":176,"line":328},[174,1179,283],{"class":194},[174,1181,1182],{"class":176,"line":350},[174,1183,394],{"class":194},[32,1185,1186,1187,1189],{},"Running ",[108,1188,157],{}," prints:",[164,1191,1196],{"className":1192,"code":1194,"language":1195,"meta":170},[1193],"language-text","handle the functionality for throttling\nRequest is valid\n","text",[108,1197,1194],{"__ignoreMap":170},[32,1199,1200,1201,1203,1204,1206,1207,1209,1210,1213],{},"Only the throttling step ran. ",[108,1202,114],{}," returns the handler it was given, so that calls can be chained. After the two chained calls, ",[108,1205,1115],{}," holds the last handler, ",[108,1208,142],{},", not the first. To run the whole chain, keep a reference to the first handler and call ",[108,1211,1212],{},"handle()"," on it:",[164,1215,1217],{"className":166,"code":1216,"language":169,"meta":170,"style":170},"Middleware middleware = new AuthenticateMiddleware();\nmiddleware.setNextHandler(new WhitelistIpMiddleware())\n        .setNextHandler(new ThrottlingMiddleware(10, 1));\n",[108,1218,1219,1233,1249],{"__ignoreMap":170},[174,1220,1221,1223,1225,1227,1229,1231],{"class":176,"line":177},[174,1222,110],{"class":180},[174,1224,1048],{"class":206},[174,1226,1051],{"class":194},[174,1228,1054],{"class":180},[174,1230,409],{"class":228},[174,1232,304],{"class":194},[174,1234,1235,1237,1239,1241,1243,1245,1247],{"class":176,"line":198},[174,1236,1115],{"class":206},[174,1238,251],{"class":194},[174,1240,1067],{"class":228},[174,1242,232],{"class":194},[174,1244,1072],{"class":180},[174,1246,580],{"class":228},[174,1248,1077],{"class":194},[174,1250,1251,1254,1256,1258,1260,1262,1264,1266,1268,1270],{"class":176,"line":213},[174,1252,1253],{"class":194},"        .",[174,1255,1067],{"class":228},[174,1257,232],{"class":194},[174,1259,1072],{"class":180},[174,1261,741],{"class":228},[174,1263,232],{"class":194},[174,1265,1094],{"class":247},[174,1267,795],{"class":194},[174,1269,1099],{"class":247},[174,1271,1102],{"class":194},[32,1273,1274,1275,251],{},"With that change, all three checks print before ",[108,1276,1277],{},"Request is valid",[1279,1280,1281],"style",{},"html pre.shiki code .sVsk0, html code.shiki .sVsk0{--shiki-default:#9D9FFE;--shiki-light:#6762D3}html pre.shiki code .sNwy7, html code.shiki .sNwy7{--shiki-default:#D4D7FE;--shiki-light:#3F3B87}html pre.shiki code .sVG6I, html code.shiki .sVG6I{--shiki-default:#85858F;--shiki-light:#71717A}html pre.shiki code .sWFPS, html code.shiki .sWFPS{--shiki-default:#C4C4CC;--shiki-light:#3F3F46}html pre.shiki code .sVz7n, html code.shiki .sVz7n{--shiki-default:#EDEDEF;--shiki-light:#0B0B0C}html pre.shiki code .sheII, html code.shiki .sheII{--shiki-default:#70ADFF;--shiki-light:#195CAE}html pre.shiki code .s4Awn, html code.shiki .s4Awn{--shiki-default:#C5DDFE;--shiki-light:#534DAF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html pre.shiki code .sUOzB, html code.shiki .sUOzB{--shiki-default:#9EC7FE;--shiki-light:#2873D1}html pre.shiki code .sFjNZ, html code.shiki .sFjNZ{--shiki-default:#6B6B74;--shiki-default-font-style:italic;--shiki-light:#8B8B94;--shiki-light-font-style:italic}",{"title":170,"searchDepth":198,"depth":198,"links":1283},[1284,1285,1286,1290,1291],{"id":29,"depth":198,"text":30},{"id":43,"depth":198,"text":44},{"id":63,"depth":198,"text":64,"children":1287},[1288,1289],{"id":68,"depth":213,"text":69},{"id":83,"depth":213,"text":84},{"id":95,"depth":198,"text":96},{"id":161,"depth":198,"text":162},"The Chain of Responsibility pattern passes a request along a line of handlers, and each one can act on it, stop it or pass it on. Explained with a worked Java example of middleware that checks web requests.","Middleware that checks a web request","md","Behavioral","lucide:link",{},"\u002Flearn\u002Fdesign-patterns\u002Fchain-of-responsibility","---\ntitle: Chain of Responsibility\ngroup: Behavioral\nicon: lucide:link\nsummary: 'Pass a request along a chain of handlers, where each one can deal with it or hand it to the next.'\ndescription: 'The Chain of Responsibility pattern passes a request along a line of handlers, and each one can act on it, stop it or pass it on. Explained with a worked Java example of middleware that checks web requests.'\nexample: 'Middleware that checks a web request'\norder: 1\nsource: https:\u002F\u002Fgithub.com\u002FHaythamasalama\u002FdesignPattern\u002Ftree\u002Fmaster\u002Fsrc\u002FBehavioral\u002FChainOfResponsibility\n---\n\n## The idea\n\nA request often needs several checks before it can be served. Is the user signed in? Is their IP address allowed? Have they sent too many requests? Putting all of these checks in one method makes it long, and every new check means editing it.\n\nThe Chain of Responsibility pattern puts each check in its own handler object. Handlers share one interface, and each holds a reference to the next handler. The sender passes the request to the first handler and doesn't know which handler, if any, will deal with it.\n\nIn the Gang of Four version, each handler either handles the request or passes it on. A common variant, used in this example and in web framework middleware, lets every handler run its check and pass the request on, while any handler can stop it.\n\n## When to use it\n\n- A request has to go through several checks or steps, and you want each one in its own class.\n- More than one object may handle a request, and the handler should be chosen at runtime.\n- You want to add, remove or reorder steps without changing the sender.\n- You are building middleware for web requests, or UI events that move from a control up to its parents.\n\n## Pros and cons\n\n### Pros\n\n- It decouples the sender of a request from the objects that handle it.\n- You can change the chain at runtime by adding, removing or reordering handlers.\n- Each handler does one job, so it is easy to test on its own.\n\n### Cons\n\n- It can be hard to follow: to know what happens to a request, you have to trace the whole chain.\n- A long chain can slow things down, and a request may reach the end without being handled.\n\n## The example\n\nThe example checks an incoming web request with three middleware steps: authentication, an IP allow list and throttling. If every step passes, the request is valid.\n\n- **`Middleware`**: the handler. An abstract class that holds the next handler, sets it with `setNextHandler()`, and offers `handleNext()`, which passes the request on, or returns `true` at the end of the chain.\n- **`AuthenticateMiddleware`**, **`WhitelistIpMiddleware`** and **`ThrottlingMiddleware`**: concrete handlers. Each prints what it checks, then either returns `false` to stop the request or calls `handleNext()` to pass it on. The checks themselves are stubs that always pass.\n- **`Demo`**: the client. It builds the chain and asks whether the request is valid.\n\n## The code\n\n```java [Middleware.java]\npublic abstract class Middleware {\n    private Middleware next;\n\n    public Middleware setNextHandler(Middleware next) {\n        this.next = next;\n\n        return next;\n    }\n\n    public abstract boolean handle();\n\n    protected boolean handleNext() {\n        if (next == null) {\n            return true;\n        }\n\n        return next.handle();\n    }\n}\n```\n\n```java [AuthenticateMiddleware.java]\npublic class AuthenticateMiddleware extends Middleware {\n    @Override\n    public boolean handle() {\n        System.out.println(\"check if user is authenticated\");\n\n        if (!checkIfAuthenticated()) {\n            System.out.println(\"User is not authenticated\");\n\n            return false;\n        }\n\n        return handleNext();\n    }\n\n    private boolean checkIfAuthenticated() {\n        return true;\n    }\n}\n```\n\n```java [WhitelistIpMiddleware.java]\npublic class WhitelistIpMiddleware extends Middleware {\n    @Override\n    public boolean handle() {\n        System.out.println(\"check if ip in database or not\");\n\n        if (!checkIp()) {\n            System.out.println(\"Ip is not in database\");\n            return false;\n        }\n\n        return handleNext();\n    }\n\n    private boolean checkIp() {\n        \u002F\u002F code to check if IP is in database\n        return true;\n    }\n}\n```\n\n```java [ThrottlingMiddleware.java]\npublic class ThrottlingMiddleware extends Middleware {\n    private final int requestPerMinute;\n    private final int request;\n\n    public ThrottlingMiddleware(int requestPerMinute, int request) {\n        this.requestPerMinute = requestPerMinute;\n        this.request = request;\n    }\n\n    @Override\n    public boolean handle() {\n        System.out.println(\"handle the functionality for throttling\");\n\n        if (checkThrottling()) {\n            System.out.println(\"Request is throttled\");\n\n            return false;\n        }\n\n        return handleNext();\n    }\n\n    private boolean checkThrottling() {\n        \u002F\u002F code to check if request is throttled\n        return false;\n    }\n}\n```\n\n```java [Demo.java]\npublic class Demo {\n    public static void main(String[] args) {\n\n        Middleware middleware = new AuthenticateMiddleware()\n                .setNextHandler(new WhitelistIpMiddleware())\n                .setNextHandler(new ThrottlingMiddleware(10, 1));\n\n        if (middleware.handle()) {\n            System.out.println(\"Request is valid\");\n        } else {\n            System.out.println(\"Request is invalid\");\n        }\n    }\n}\n```\n\nRunning `Demo` prints:\n\n```text\nhandle the functionality for throttling\nRequest is valid\n```\n\nOnly the throttling step ran. `setNextHandler()` returns the handler it was given, so that calls can be chained. After the two chained calls, `middleware` holds the last handler, `ThrottlingMiddleware`, not the first. To run the whole chain, keep a reference to the first handler and call `handle()` on it:\n\n```java\nMiddleware middleware = new AuthenticateMiddleware();\nmiddleware.setNextHandler(new WhitelistIpMiddleware())\n        .setNextHandler(new ThrottlingMiddleware(10, 1));\n```\n\nWith that change, all three checks print before `Request is valid`.\n",{"title":22,"description":1292},{"loc":1298},"https:\u002F\u002Fgithub.com\u002FHaythamasalama\u002FdesignPattern\u002Ftree\u002Fmaster\u002Fsrc\u002FBehavioral\u002FChainOfResponsibility","learn\u002Fdesign-patterns\u002Fchain-of-responsibility","Pass a request along a chain of handlers, where each one can deal with it or hand it to the next.","ezbnQ2dBhpE6OJEU8sFX98kFH3JRGjEELaUWhzxTFVs",[1307,1308,1313,1318,1323,1328,1333,1338],{"path":1298,"title":22,"icon":1296,"summary":1304,"order":177},{"path":1309,"title":1310,"icon":1311,"summary":1312,"order":198},"\u002Flearn\u002Fdesign-patterns\u002Fcommand","Command","lucide:square-terminal","Turn a request into an object, so it can be passed around, queued, logged or undone.",{"path":1314,"title":1315,"icon":1316,"summary":1317,"order":213},"\u002Flearn\u002Fdesign-patterns\u002Fiterator","Iterator","lucide:list-ordered","Walk through the items of a collection one by one, without knowing how the collection stores them.",{"path":1319,"title":1320,"icon":1321,"summary":1322,"order":220},"\u002Flearn\u002Fdesign-patterns\u002Fobserver","Observer","lucide:bell","One object announces a change, and every object that subscribed to it hears about it.",{"path":1324,"title":1325,"icon":1326,"summary":1327,"order":244},"\u002Flearn\u002Fdesign-patterns\u002Fstate","State","lucide:toggle-left","An object changes its behaviour when its internal state changes, as if it had changed its class.",{"path":1329,"title":1330,"icon":1331,"summary":1332,"order":265},"\u002Flearn\u002Fdesign-patterns\u002Fstrategy","Strategy","lucide:shuffle","Put each way of doing a task in its own class, and choose which one to use while the program runs.",{"path":1334,"title":1335,"icon":1336,"summary":1337,"order":270},"\u002Flearn\u002Fdesign-patterns\u002Ftemplate-method","Template Method","lucide:layout-template","A base class fixes the steps of a task, and subclasses fill in the steps that differ.",{"path":1339,"title":1340,"icon":1341,"summary":1342,"order":280},"\u002Flearn\u002Fdesign-patterns\u002Fvisitor","Visitor","lucide:footprints","Add new operations to a set of classes without changing them, by moving each operation into its own visitor.",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1344},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 14c.2-1 .7-1.7 1.5-2.5c1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5c.7.7 1.3 1.5 1.5 2.5m0 4h6m-5 4h4\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1346},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Crect width=\"8\" height=\"8\" x=\"3\" y=\"3\" rx=\"2\"\u002F>\u003Cpath d=\"M7 11v4a2 2 0 0 0 2 2h4\"\u002F>\u003Crect width=\"8\" height=\"8\" x=\"13\" y=\"13\" rx=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1348},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"\u002F>\u003Cpath d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1350},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m7 11l2-2l-2-2m4 6h4\"\u002F>\u003Crect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\" ry=\"2\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1352},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M11 5h10m-10 7h10m-10 7h10M4 4h1v5M4 9h2m.5 11H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1354},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M10.268 21a2 2 0 0 0 3.464 0m-10.47-5.674A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1356},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Ccircle cx=\"9\" cy=\"12\" r=\"3\"\u002F>\u003Crect width=\"20\" height=\"14\" x=\"2\" y=\"5\" rx=\"7\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1358},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Cpath d=\"m18 14l4 4l-4 4m0-20l4 4l-4 4\"\u002F>\u003Cpath d=\"M2 18h1.973a4 4 0 0 0 3.3-1.7l5.454-8.6a4 4 0 0 1 3.3-1.7H22M2 6h1.972a4 4 0 0 1 3.6 2.2M22 18h-6.041a4 4 0 0 1-3.3-1.8l-.359-.45\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1360},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Crect width=\"18\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\"\u002F>\u003Crect width=\"9\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\"\u002F>\u003Crect width=\"5\" height=\"7\" x=\"16\" y=\"14\" rx=\"1\"\u002F>\u003C\u002Fg>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1362},"\u003Cpath fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 16v-2.38C4 11.5 2.97 10.5 3 8c.03-2.72 1.49-6 4.5-6C9.37 2 10 3.8 10 5.5c0 3.11-2 5.66-2 8.68V16a2 2 0 1 1-4 0m16 4v-2.38c0-2.12 1.03-3.12 1-5.62c-.03-2.72-1.49-6-4.5-6C14.63 6 14 7.8 14 9.5c0 3.11 2 5.66 2 8.68V20a2 2 0 1 0 4 0m-4-3h4M4 13h4\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1364},"\u003Cg fill=\"none\" stroke=\"currentColor\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\">\u003Crect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"\u002F>\u003Cpath d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"\u002F>\u003C\u002Fg>",1793131416702]