[{"data":1,"prerenderedAt":1175},["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\u002Fstate":20,"pattern-group:\u002Flearn\u002Fdesign-patterns\u002Fstate":1116,"i-lucide:lightbulb":1153,"i-lucide:workflow":1155,"i-lucide:link":1157,"i-lucide:square-terminal":1159,"i-lucide:list-ordered":1161,"i-lucide:bell":1163,"i-lucide:toggle-left":1165,"i-lucide:shuffle":1167,"i-lucide:layout-template":1169,"i-lucide:footprints":1171,"i-lucide:copy":1173},{"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":1102,"example":1103,"extension":1104,"group":1105,"icon":1106,"meta":1107,"navigation":267,"order":292,"path":1108,"rawbody":1109,"seo":1110,"sitemap":1111,"source":1112,"stem":1113,"summary":1114,"__hash__":1115},"patterns\u002Flearn\u002Fdesign-patterns\u002Fstate.md","State",{"type":24,"value":25,"toc":1092},"minimark",[26,31,44,47,50,54,76,80,85,99,103,117,121,132,200,209,213,342,501,613,716,819,922,1074,1080,1088],[27,28,30],"h2",{"id":29},"the-idea","The idea",[32,33,34,35,39,40,43],"p",{},"Many objects behave differently depending on the state they are in. A transaction that is pending, approved or cancelled responds differently to the same request. The usual way to code this is a ",[36,37,38],"code",{},"switch"," or a chain of ",[36,41,42],{},"if"," statements on a status field, repeated in every method. Each new state means editing all of them.",[32,45,46],{},"The State pattern gives each state its own class, and all the state classes share one interface. The main object, the context, holds a reference to its current state and passes each request to it. To change its behaviour, the context swaps in a different state object.",[32,48,49],{},"From the outside, the context seems to change its class. Inside, the logic for each state sits in one place.",[27,51,53],{"id":52},"when-to-use-it","When to use it",[55,56,57,61,70,73],"ul",{},[58,59,60],"li",{},"An object's behaviour depends on its state, and it must change that behaviour at runtime.",[58,62,63,64,66,67,69],{},"Methods are full of ",[36,65,38],{}," or ",[36,68,42],{}," statements on the same status field.",[58,71,72],{},"The object goes through a clear lifecycle, such as an order, a document review or a network connection.",[58,74,75],{},"You expect to add new states, and want each one in its own class.",[27,77,79],{"id":78},"pros-and-cons","Pros and cons",[81,82,84],"h3",{"id":83},"pros","Pros",[55,86,87,93,96],{},[58,88,89,90,92],{},"It is more flexible and has fewer branches: the ",[36,91,42],{}," chains on the status go away.",[58,94,95],{},"Adding a new state is easy: write one class.",[58,97,98],{},"The code for each state sits in one class, so it is easier to read and to test.",[81,100,102],{"id":101},"cons","Cons",[55,104,105,108,114],{},[58,106,107],{},"The code is more complex, with one more class in the system for every state.",[58,109,110,111,113],{},"For an object with two or three simple states, a plain field and a ",[36,112,38],{}," can be clearer.",[58,115,116],{},"The transitions are spread across classes, so the full lifecycle is harder to see at a glance.",[27,118,120],{"id":119},"the-example","The example",[32,122,123,124,127,128,131],{},"The example is a payment transaction. A new transaction starts as pending. The demo then moves it to ",[36,125,126],{},"ApprovingState"," and then to ",[36,129,130],{},"PressedState",", and each state handles the request in its own way.",[55,133,134,146,168,192],{},[58,135,136,141,142,145],{},[137,138,139],"strong",{},[36,140,22],{},": the state. An abstract class that holds the transaction and declares ",[36,143,144],{},"handle()",".",[58,147,148,153,154,157,158,161,162,165,166,145],{},[137,149,150],{},[36,151,152],{},"Transaction",": the context. It starts in ",[36,155,156],{},"PendingState",", can switch state with ",[36,159,160],{},"setState()",", and passes each ",[36,163,164],{},"request()"," to the current state's ",[36,167,144],{},[58,169,170,174,175,174,179,183,184,189,190,145],{},[137,171,172],{},[36,173,156],{},", ",[137,176,177],{},[36,178,126],{},[137,180,181],{},[36,182,130],{}," and ",[137,185,186],{},[36,187,188],{},"CancelingState",": concrete states. Each prints which state handled the request. The demo doesn't use ",[36,191,188],{},[58,193,194,199],{},[137,195,196],{},[36,197,198],{},"Demo",": the client. It sends one request in each state.",[32,201,202,203,205,206,208],{},"Here, ",[36,204,198],{}," moves the transaction from one state to the next. In the Gang of Four book, either the context or the state classes decide the next state. Each state already holds the transaction, so it could call ",[36,207,160],{}," itself.",[27,210,212],{"id":211},"the-code","The code",[214,215,221],"pre",{"className":216,"code":217,"filename":218,"language":219,"meta":220,"style":220},"language-java shiki shiki-themes haytham-dark haytham-light","public abstract class State {\n    protected Transaction transaction;\n\n    public State(Transaction transaction) {\n        this.transaction = transaction;\n    }\n\n    abstract void handle();\n}\n","State.java","java","",[36,222,223,246,262,269,290,310,316,321,336],{"__ignoreMap":220},[224,225,228,232,235,238,242],"span",{"class":226,"line":227},"line",1,[224,229,231],{"class":230},"sVsk0","public",[224,233,234],{"class":230}," abstract",[224,236,237],{"class":230}," class",[224,239,241],{"class":240},"sNwy7"," State",[224,243,245],{"class":244},"sVG6I"," {\n",[224,247,249,252,255,259],{"class":226,"line":248},2,[224,250,251],{"class":230},"    protected",[224,253,254],{"class":230}," Transaction",[224,256,258],{"class":257},"sWFPS"," transaction",[224,260,261],{"class":244},";\n",[224,263,265],{"class":226,"line":264},3,[224,266,268],{"emptyLinePlaceholder":267},true,"\n",[224,270,272,275,278,281,283,285,288],{"class":226,"line":271},4,[224,273,274],{"class":230},"    public",[224,276,241],{"class":277},"sVz7n",[224,279,280],{"class":244},"(",[224,282,152],{"class":230},[224,284,258],{"class":257},[224,286,287],{"class":244},")",[224,289,245],{"class":244},[224,291,293,297,299,303,306,308],{"class":226,"line":292},5,[224,294,296],{"class":295},"sheII","        this",[224,298,145],{"class":244},[224,300,302],{"class":301},"s4Awn","transaction",[224,304,305],{"class":244}," =",[224,307,258],{"class":257},[224,309,261],{"class":244},[224,311,313],{"class":226,"line":312},6,[224,314,315],{"class":244},"    }\n",[224,317,319],{"class":226,"line":318},7,[224,320,268],{"emptyLinePlaceholder":267},[224,322,324,327,330,333],{"class":226,"line":323},8,[224,325,326],{"class":230},"    abstract",[224,328,329],{"class":230}," void",[224,331,332],{"class":277}," handle",[224,334,335],{"class":244},"();\n",[224,337,339],{"class":226,"line":338},9,[224,340,341],{"class":244},"}\n",[214,343,346],{"className":216,"code":344,"filename":345,"language":219,"meta":220,"style":220},"public class Transaction {\n    private State state;\n\n    public Transaction() {\n        this.state = new PendingState(this);\n    }\n\n    public void setState(State state) {\n        this.state = state;\n    }\n\n    public void request() {\n        this.state.handle();\n    }\n}\n","Transaction.java",[36,347,348,358,370,374,385,410,414,418,437,451,456,461,475,491,496],{"__ignoreMap":220},[224,349,350,352,354,356],{"class":226,"line":227},[224,351,231],{"class":230},[224,353,237],{"class":230},[224,355,254],{"class":240},[224,357,245],{"class":244},[224,359,360,363,365,368],{"class":226,"line":248},[224,361,362],{"class":230},"    private",[224,364,241],{"class":230},[224,366,367],{"class":257}," state",[224,369,261],{"class":244},[224,371,372],{"class":226,"line":264},[224,373,268],{"emptyLinePlaceholder":267},[224,375,376,378,380,383],{"class":226,"line":271},[224,377,274],{"class":230},[224,379,254],{"class":277},[224,381,382],{"class":244},"()",[224,384,245],{"class":244},[224,386,387,389,391,394,396,399,402,404,407],{"class":226,"line":292},[224,388,296],{"class":295},[224,390,145],{"class":244},[224,392,393],{"class":301},"state",[224,395,305],{"class":244},[224,397,398],{"class":230}," new",[224,400,401],{"class":277}," PendingState",[224,403,280],{"class":244},[224,405,406],{"class":295},"this",[224,408,409],{"class":244},");\n",[224,411,412],{"class":226,"line":312},[224,413,315],{"class":244},[224,415,416],{"class":226,"line":318},[224,417,268],{"emptyLinePlaceholder":267},[224,419,420,422,424,427,429,431,433,435],{"class":226,"line":323},[224,421,274],{"class":230},[224,423,329],{"class":230},[224,425,426],{"class":277}," setState",[224,428,280],{"class":244},[224,430,22],{"class":230},[224,432,367],{"class":257},[224,434,287],{"class":244},[224,436,245],{"class":244},[224,438,439,441,443,445,447,449],{"class":226,"line":338},[224,440,296],{"class":295},[224,442,145],{"class":244},[224,444,393],{"class":301},[224,446,305],{"class":244},[224,448,367],{"class":257},[224,450,261],{"class":244},[224,452,454],{"class":226,"line":453},10,[224,455,315],{"class":244},[224,457,459],{"class":226,"line":458},11,[224,460,268],{"emptyLinePlaceholder":267},[224,462,464,466,468,471,473],{"class":226,"line":463},12,[224,465,274],{"class":230},[224,467,329],{"class":230},[224,469,470],{"class":277}," request",[224,472,382],{"class":244},[224,474,245],{"class":244},[224,476,478,480,482,484,486,489],{"class":226,"line":477},13,[224,479,296],{"class":295},[224,481,145],{"class":244},[224,483,393],{"class":301},[224,485,145],{"class":244},[224,487,488],{"class":277},"handle",[224,490,335],{"class":244},[224,492,494],{"class":226,"line":493},14,[224,495,315],{"class":244},[224,497,499],{"class":226,"line":498},15,[224,500,341],{"class":244},[214,502,505],{"className":216,"code":503,"filename":504,"language":219,"meta":220,"style":220},"public class PendingState extends State {\n    public PendingState(Transaction transaction) {\n        super(transaction);\n    }\n\n    @Override\n    void handle() {\n        \u002F\u002F Your implementation for pending state transaction.\n        System.out.println(\"handle pending state transaction\");\n    }\n}\n","PendingState.java",[36,506,507,522,538,549,553,557,565,576,582,605,609],{"__ignoreMap":220},[224,508,509,511,513,515,518,520],{"class":226,"line":227},[224,510,231],{"class":230},[224,512,237],{"class":230},[224,514,401],{"class":240},[224,516,517],{"class":230}," extends",[224,519,241],{"class":240},[224,521,245],{"class":244},[224,523,524,526,528,530,532,534,536],{"class":226,"line":248},[224,525,274],{"class":230},[224,527,401],{"class":277},[224,529,280],{"class":244},[224,531,152],{"class":230},[224,533,258],{"class":257},[224,535,287],{"class":244},[224,537,245],{"class":244},[224,539,540,543,545,547],{"class":226,"line":264},[224,541,542],{"class":295},"        super",[224,544,280],{"class":244},[224,546,302],{"class":257},[224,548,409],{"class":244},[224,550,551],{"class":226,"line":271},[224,552,315],{"class":244},[224,554,555],{"class":226,"line":292},[224,556,268],{"emptyLinePlaceholder":267},[224,558,559,562],{"class":226,"line":312},[224,560,561],{"class":244},"    @",[224,563,564],{"class":230},"Override\n",[224,566,567,570,572,574],{"class":226,"line":318},[224,568,569],{"class":230},"    void",[224,571,332],{"class":277},[224,573,382],{"class":244},[224,575,245],{"class":244},[224,577,578],{"class":226,"line":323},[224,579,581],{"class":580},"sFjNZ","        \u002F\u002F Your implementation for pending state transaction.\n",[224,583,584,587,589,592,594,597,599,603],{"class":226,"line":338},[224,585,586],{"class":257},"        System",[224,588,145],{"class":244},[224,590,591],{"class":301},"out",[224,593,145],{"class":244},[224,595,596],{"class":277},"println",[224,598,280],{"class":244},[224,600,602],{"class":601},"sUOzB","\"handle pending state transaction\"",[224,604,409],{"class":244},[224,606,607],{"class":226,"line":453},[224,608,315],{"class":244},[224,610,611],{"class":226,"line":458},[224,612,341],{"class":244},[214,614,617],{"className":216,"code":615,"filename":616,"language":219,"meta":220,"style":220},"public class ApprovingState extends State {\n    public ApprovingState(Transaction transaction) {\n        super(transaction);\n    }\n\n    @Override\n    void handle() {\n        \u002F\u002F Your implementation for approved state transaction.\n        System.out.println(\"handle approved state transaction\");\n    }\n}\n","ApprovingState.java",[36,618,619,634,650,660,664,668,674,684,689,708,712],{"__ignoreMap":220},[224,620,621,623,625,628,630,632],{"class":226,"line":227},[224,622,231],{"class":230},[224,624,237],{"class":230},[224,626,627],{"class":240}," ApprovingState",[224,629,517],{"class":230},[224,631,241],{"class":240},[224,633,245],{"class":244},[224,635,636,638,640,642,644,646,648],{"class":226,"line":248},[224,637,274],{"class":230},[224,639,627],{"class":277},[224,641,280],{"class":244},[224,643,152],{"class":230},[224,645,258],{"class":257},[224,647,287],{"class":244},[224,649,245],{"class":244},[224,651,652,654,656,658],{"class":226,"line":264},[224,653,542],{"class":295},[224,655,280],{"class":244},[224,657,302],{"class":257},[224,659,409],{"class":244},[224,661,662],{"class":226,"line":271},[224,663,315],{"class":244},[224,665,666],{"class":226,"line":292},[224,667,268],{"emptyLinePlaceholder":267},[224,669,670,672],{"class":226,"line":312},[224,671,561],{"class":244},[224,673,564],{"class":230},[224,675,676,678,680,682],{"class":226,"line":318},[224,677,569],{"class":230},[224,679,332],{"class":277},[224,681,382],{"class":244},[224,683,245],{"class":244},[224,685,686],{"class":226,"line":323},[224,687,688],{"class":580},"        \u002F\u002F Your implementation for approved state transaction.\n",[224,690,691,693,695,697,699,701,703,706],{"class":226,"line":338},[224,692,586],{"class":257},[224,694,145],{"class":244},[224,696,591],{"class":301},[224,698,145],{"class":244},[224,700,596],{"class":277},[224,702,280],{"class":244},[224,704,705],{"class":601},"\"handle approved state transaction\"",[224,707,409],{"class":244},[224,709,710],{"class":226,"line":453},[224,711,315],{"class":244},[224,713,714],{"class":226,"line":458},[224,715,341],{"class":244},[214,717,720],{"className":216,"code":718,"filename":719,"language":219,"meta":220,"style":220},"public class PressedState extends State {\n    public PressedState(Transaction transaction) {\n        super(transaction);\n    }\n\n    @Override\n    void handle() {\n        \u002F\u002F Your implementation for pressed state transaction.\n        System.out.println(\"handle pressed state transaction\");\n    }\n}\n","PressedState.java",[36,721,722,737,753,763,767,771,777,787,792,811,815],{"__ignoreMap":220},[224,723,724,726,728,731,733,735],{"class":226,"line":227},[224,725,231],{"class":230},[224,727,237],{"class":230},[224,729,730],{"class":240}," PressedState",[224,732,517],{"class":230},[224,734,241],{"class":240},[224,736,245],{"class":244},[224,738,739,741,743,745,747,749,751],{"class":226,"line":248},[224,740,274],{"class":230},[224,742,730],{"class":277},[224,744,280],{"class":244},[224,746,152],{"class":230},[224,748,258],{"class":257},[224,750,287],{"class":244},[224,752,245],{"class":244},[224,754,755,757,759,761],{"class":226,"line":264},[224,756,542],{"class":295},[224,758,280],{"class":244},[224,760,302],{"class":257},[224,762,409],{"class":244},[224,764,765],{"class":226,"line":271},[224,766,315],{"class":244},[224,768,769],{"class":226,"line":292},[224,770,268],{"emptyLinePlaceholder":267},[224,772,773,775],{"class":226,"line":312},[224,774,561],{"class":244},[224,776,564],{"class":230},[224,778,779,781,783,785],{"class":226,"line":318},[224,780,569],{"class":230},[224,782,332],{"class":277},[224,784,382],{"class":244},[224,786,245],{"class":244},[224,788,789],{"class":226,"line":323},[224,790,791],{"class":580},"        \u002F\u002F Your implementation for pressed state transaction.\n",[224,793,794,796,798,800,802,804,806,809],{"class":226,"line":338},[224,795,586],{"class":257},[224,797,145],{"class":244},[224,799,591],{"class":301},[224,801,145],{"class":244},[224,803,596],{"class":277},[224,805,280],{"class":244},[224,807,808],{"class":601},"\"handle pressed state transaction\"",[224,810,409],{"class":244},[224,812,813],{"class":226,"line":453},[224,814,315],{"class":244},[224,816,817],{"class":226,"line":458},[224,818,341],{"class":244},[214,820,823],{"className":216,"code":821,"filename":822,"language":219,"meta":220,"style":220},"public class CancelingState extends State {\n    public CancelingState(Transaction transaction) {\n        super(transaction);\n    }\n\n    @Override\n    void handle() {\n        \u002F\u002F Your implementation for canceled state transaction.\n        System.out.println(\"handle canceled state transaction\");\n    }\n}\n","CancelingState.java",[36,824,825,840,856,866,870,874,880,890,895,914,918],{"__ignoreMap":220},[224,826,827,829,831,834,836,838],{"class":226,"line":227},[224,828,231],{"class":230},[224,830,237],{"class":230},[224,832,833],{"class":240}," CancelingState",[224,835,517],{"class":230},[224,837,241],{"class":240},[224,839,245],{"class":244},[224,841,842,844,846,848,850,852,854],{"class":226,"line":248},[224,843,274],{"class":230},[224,845,833],{"class":277},[224,847,280],{"class":244},[224,849,152],{"class":230},[224,851,258],{"class":257},[224,853,287],{"class":244},[224,855,245],{"class":244},[224,857,858,860,862,864],{"class":226,"line":264},[224,859,542],{"class":295},[224,861,280],{"class":244},[224,863,302],{"class":257},[224,865,409],{"class":244},[224,867,868],{"class":226,"line":271},[224,869,315],{"class":244},[224,871,872],{"class":226,"line":292},[224,873,268],{"emptyLinePlaceholder":267},[224,875,876,878],{"class":226,"line":312},[224,877,561],{"class":244},[224,879,564],{"class":230},[224,881,882,884,886,888],{"class":226,"line":318},[224,883,569],{"class":230},[224,885,332],{"class":277},[224,887,382],{"class":244},[224,889,245],{"class":244},[224,891,892],{"class":226,"line":323},[224,893,894],{"class":580},"        \u002F\u002F Your implementation for canceled state transaction.\n",[224,896,897,899,901,903,905,907,909,912],{"class":226,"line":338},[224,898,586],{"class":257},[224,900,145],{"class":244},[224,902,591],{"class":301},[224,904,145],{"class":244},[224,906,596],{"class":277},[224,908,280],{"class":244},[224,910,911],{"class":601},"\"handle canceled state transaction\"",[224,913,409],{"class":244},[224,915,916],{"class":226,"line":453},[224,917,315],{"class":244},[224,919,920],{"class":226,"line":458},[224,921,341],{"class":244},[214,923,926],{"className":216,"code":924,"filename":925,"language":219,"meta":220,"style":220},"public class Demo {\n    public static void main(String[] args) {\n        Transaction transaction = new Transaction();\n        transaction.request();\n\n        transaction.setState(new ApprovingState(transaction));\n        transaction.request();\n\n        transaction.setState(new PressedState(transaction));\n        transaction.request();\n    }\n}\n","Demo.java",[36,927,928,939,966,983,995,999,1022,1032,1036,1056,1066,1070],{"__ignoreMap":220},[224,929,930,932,934,937],{"class":226,"line":227},[224,931,231],{"class":230},[224,933,237],{"class":230},[224,935,936],{"class":240}," Demo",[224,938,245],{"class":244},[224,940,941,943,946,948,951,953,956,959,962,964],{"class":226,"line":248},[224,942,274],{"class":230},[224,944,945],{"class":230}," static",[224,947,329],{"class":230},[224,949,950],{"class":277}," main",[224,952,280],{"class":244},[224,954,955],{"class":230},"String",[224,957,958],{"class":244},"[]",[224,960,961],{"class":257}," args",[224,963,287],{"class":244},[224,965,245],{"class":244},[224,967,968,971,974,977,979,981],{"class":226,"line":264},[224,969,970],{"class":230},"        Transaction",[224,972,973],{"class":257}," transaction ",[224,975,976],{"class":244},"=",[224,978,398],{"class":230},[224,980,254],{"class":277},[224,982,335],{"class":244},[224,984,985,988,990,993],{"class":226,"line":271},[224,986,987],{"class":257},"        transaction",[224,989,145],{"class":244},[224,991,992],{"class":277},"request",[224,994,335],{"class":244},[224,996,997],{"class":226,"line":292},[224,998,268],{"emptyLinePlaceholder":267},[224,1000,1001,1003,1005,1008,1010,1013,1015,1017,1019],{"class":226,"line":312},[224,1002,987],{"class":257},[224,1004,145],{"class":244},[224,1006,1007],{"class":277},"setState",[224,1009,280],{"class":244},[224,1011,1012],{"class":230},"new",[224,1014,627],{"class":277},[224,1016,280],{"class":244},[224,1018,302],{"class":257},[224,1020,1021],{"class":244},"));\n",[224,1023,1024,1026,1028,1030],{"class":226,"line":318},[224,1025,987],{"class":257},[224,1027,145],{"class":244},[224,1029,992],{"class":277},[224,1031,335],{"class":244},[224,1033,1034],{"class":226,"line":323},[224,1035,268],{"emptyLinePlaceholder":267},[224,1037,1038,1040,1042,1044,1046,1048,1050,1052,1054],{"class":226,"line":338},[224,1039,987],{"class":257},[224,1041,145],{"class":244},[224,1043,1007],{"class":277},[224,1045,280],{"class":244},[224,1047,1012],{"class":230},[224,1049,730],{"class":277},[224,1051,280],{"class":244},[224,1053,302],{"class":257},[224,1055,1021],{"class":244},[224,1057,1058,1060,1062,1064],{"class":226,"line":453},[224,1059,987],{"class":257},[224,1061,145],{"class":244},[224,1063,992],{"class":277},[224,1065,335],{"class":244},[224,1067,1068],{"class":226,"line":458},[224,1069,315],{"class":244},[224,1071,1072],{"class":226,"line":463},[224,1073,341],{"class":244},[32,1075,1076,1077,1079],{},"Running ",[36,1078,198],{}," prints:",[214,1081,1086],{"className":1082,"code":1084,"language":1085,"meta":220},[1083],"language-text","handle pending state transaction\nhandle approved state transaction\nhandle pressed state transaction\n","text",[36,1087,1084],{"__ignoreMap":220},[1089,1090,1091],"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 .sFjNZ, html code.shiki .sFjNZ{--shiki-default:#6B6B74;--shiki-default-font-style:italic;--shiki-light:#8B8B94;--shiki-light-font-style:italic}html pre.shiki code .sUOzB, html code.shiki .sUOzB{--shiki-default:#9EC7FE;--shiki-light:#2873D1}",{"title":220,"searchDepth":248,"depth":248,"links":1093},[1094,1095,1096,1100,1101],{"id":29,"depth":248,"text":30},{"id":52,"depth":248,"text":53},{"id":78,"depth":248,"text":79,"children":1097},[1098,1099],{"id":83,"depth":264,"text":84},{"id":101,"depth":264,"text":102},{"id":119,"depth":248,"text":120},{"id":211,"depth":248,"text":212},"The State pattern lets an object change its behaviour when its internal state changes, with one class per state instead of long chains of if statements. Explained with a worked Java example of a transaction.","A transaction that moves from pending to approved","md","Behavioral","lucide:toggle-left",{},"\u002Flearn\u002Fdesign-patterns\u002Fstate","---\ntitle: State\ngroup: Behavioral\nicon: lucide:toggle-left\nsummary: 'An object changes its behaviour when its internal state changes, as if it had changed its class.'\ndescription: 'The State pattern lets an object change its behaviour when its internal state changes, with one class per state instead of long chains of if statements. Explained with a worked Java example of a transaction.'\nexample: 'A transaction that moves from pending to approved'\norder: 5\nsource: https:\u002F\u002Fgithub.com\u002FHaythamasalama\u002FdesignPattern\u002Ftree\u002Fmaster\u002Fsrc\u002FBehavioral\u002FState\n---\n\n## The idea\n\nMany objects behave differently depending on the state they are in. A transaction that is pending, approved or cancelled responds differently to the same request. The usual way to code this is a `switch` or a chain of `if` statements on a status field, repeated in every method. Each new state means editing all of them.\n\nThe State pattern gives each state its own class, and all the state classes share one interface. The main object, the context, holds a reference to its current state and passes each request to it. To change its behaviour, the context swaps in a different state object.\n\nFrom the outside, the context seems to change its class. Inside, the logic for each state sits in one place.\n\n## When to use it\n\n- An object's behaviour depends on its state, and it must change that behaviour at runtime.\n- Methods are full of `switch` or `if` statements on the same status field.\n- The object goes through a clear lifecycle, such as an order, a document review or a network connection.\n- You expect to add new states, and want each one in its own class.\n\n## Pros and cons\n\n### Pros\n\n- It is more flexible and has fewer branches: the `if` chains on the status go away.\n- Adding a new state is easy: write one class.\n- The code for each state sits in one class, so it is easier to read and to test.\n\n### Cons\n\n- The code is more complex, with one more class in the system for every state.\n- For an object with two or three simple states, a plain field and a `switch` can be clearer.\n- The transitions are spread across classes, so the full lifecycle is harder to see at a glance.\n\n## The example\n\nThe example is a payment transaction. A new transaction starts as pending. The demo then moves it to `ApprovingState` and then to `PressedState`, and each state handles the request in its own way.\n\n- **`State`**: the state. An abstract class that holds the transaction and declares `handle()`.\n- **`Transaction`**: the context. It starts in `PendingState`, can switch state with `setState()`, and passes each `request()` to the current state's `handle()`.\n- **`PendingState`**, **`ApprovingState`**, **`PressedState`** and **`CancelingState`**: concrete states. Each prints which state handled the request. The demo doesn't use `CancelingState`.\n- **`Demo`**: the client. It sends one request in each state.\n\nHere, `Demo` moves the transaction from one state to the next. In the Gang of Four book, either the context or the state classes decide the next state. Each state already holds the transaction, so it could call `setState()` itself.\n\n## The code\n\n```java [State.java]\npublic abstract class State {\n    protected Transaction transaction;\n\n    public State(Transaction transaction) {\n        this.transaction = transaction;\n    }\n\n    abstract void handle();\n}\n```\n\n```java [Transaction.java]\npublic class Transaction {\n    private State state;\n\n    public Transaction() {\n        this.state = new PendingState(this);\n    }\n\n    public void setState(State state) {\n        this.state = state;\n    }\n\n    public void request() {\n        this.state.handle();\n    }\n}\n```\n\n```java [PendingState.java]\npublic class PendingState extends State {\n    public PendingState(Transaction transaction) {\n        super(transaction);\n    }\n\n    @Override\n    void handle() {\n        \u002F\u002F Your implementation for pending state transaction.\n        System.out.println(\"handle pending state transaction\");\n    }\n}\n```\n\n```java [ApprovingState.java]\npublic class ApprovingState extends State {\n    public ApprovingState(Transaction transaction) {\n        super(transaction);\n    }\n\n    @Override\n    void handle() {\n        \u002F\u002F Your implementation for approved state transaction.\n        System.out.println(\"handle approved state transaction\");\n    }\n}\n```\n\n```java [PressedState.java]\npublic class PressedState extends State {\n    public PressedState(Transaction transaction) {\n        super(transaction);\n    }\n\n    @Override\n    void handle() {\n        \u002F\u002F Your implementation for pressed state transaction.\n        System.out.println(\"handle pressed state transaction\");\n    }\n}\n```\n\n```java [CancelingState.java]\npublic class CancelingState extends State {\n    public CancelingState(Transaction transaction) {\n        super(transaction);\n    }\n\n    @Override\n    void handle() {\n        \u002F\u002F Your implementation for canceled state transaction.\n        System.out.println(\"handle canceled state transaction\");\n    }\n}\n```\n\n```java [Demo.java]\npublic class Demo {\n    public static void main(String[] args) {\n        Transaction transaction = new Transaction();\n        transaction.request();\n\n        transaction.setState(new ApprovingState(transaction));\n        transaction.request();\n\n        transaction.setState(new PressedState(transaction));\n        transaction.request();\n    }\n}\n```\n\nRunning `Demo` prints:\n\n```text\nhandle pending state transaction\nhandle approved state transaction\nhandle pressed state transaction\n```\n",{"title":22,"description":1102},{"loc":1108},"https:\u002F\u002Fgithub.com\u002FHaythamasalama\u002FdesignPattern\u002Ftree\u002Fmaster\u002Fsrc\u002FBehavioral\u002FState","learn\u002Fdesign-patterns\u002Fstate","An object changes its behaviour when its internal state changes, as if it had changed its class.","d9qn3VMtMbVo6ox8fL4C7eD4MY0wWmyvp7NRZ-ebNzQ",[1117,1122,1127,1132,1137,1138,1143,1148],{"path":1118,"title":1119,"icon":1120,"summary":1121,"order":227},"\u002Flearn\u002Fdesign-patterns\u002Fchain-of-responsibility","Chain of Responsibility","lucide:link","Pass a request along a chain of handlers, where each one can deal with it or hand it to the next.",{"path":1123,"title":1124,"icon":1125,"summary":1126,"order":248},"\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":1128,"title":1129,"icon":1130,"summary":1131,"order":264},"\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":1133,"title":1134,"icon":1135,"summary":1136,"order":271},"\u002Flearn\u002Fdesign-patterns\u002Fobserver","Observer","lucide:bell","One object announces a change, and every object that subscribed to it hears about it.",{"path":1108,"title":22,"icon":1106,"summary":1114,"order":292},{"path":1139,"title":1140,"icon":1141,"summary":1142,"order":312},"\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":1144,"title":1145,"icon":1146,"summary":1147,"order":318},"\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":1149,"title":1150,"icon":1151,"summary":1152,"order":323},"\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":1154},"\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":1156},"\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":1158},"\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":1160},"\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":1162},"\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":1164},"\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":1166},"\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":1168},"\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":1170},"\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":1172},"\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":1174},"\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>",1793131416941]