[{"data":1,"prerenderedAt":1038},["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\u002Fobserver":20,"pattern-group:\u002Flearn\u002Fdesign-patterns\u002Fobserver":979,"i-lucide:lightbulb":1016,"i-lucide:workflow":1018,"i-lucide:link":1020,"i-lucide:square-terminal":1022,"i-lucide:list-ordered":1024,"i-lucide:bell":1026,"i-lucide:toggle-left":1028,"i-lucide:shuffle":1030,"i-lucide:layout-template":1032,"i-lucide:footprints":1034,"i-lucide:copy":1036},{"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":965,"example":966,"extension":967,"group":968,"icon":969,"meta":970,"navigation":345,"order":244,"path":971,"rawbody":972,"seo":973,"sitemap":974,"source":975,"stem":976,"summary":977,"__hash__":978},"patterns\u002Flearn\u002Fdesign-patterns\u002Fobserver.md","Observer",{"type":24,"value":25,"toc":955},"minimark",[26,31,35,38,41,45,61,65,70,81,85,96,100,103,167,170,174,259,297,662,813,938,944,951],[27,28,30],"h2",{"id":29},"the-idea","The idea",[32,33,34],"p",{},"Often several objects need to react when something happens to another object. When a tweet is posted, every follower should hear about it. The tweet could call each follower directly, but then it would need to know every kind of object that cares, and change whenever a new one appears.",[32,36,37],{},"The Observer pattern turns this around. The object being watched, the subject, keeps a list of observers. Observers subscribe to it and can unsubscribe at any time. When something happens, the subject goes through its list and calls the same method on each observer. All it knows about them is that they implement the observer interface.",[32,39,40],{},"This gives a one-to-many relationship with loose coupling. The subject doesn't know what its observers do, and you can add new kinds of observers without changing 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 change to one object should update others, and you don't know in advance how many or which ones.",[49,53,54],{},"You want objects to subscribe and unsubscribe while the program runs.",[49,56,57],{},"You are building events: a button click, a new message, a price change.",[49,59,60],{},"You want to keep a model separate from the views that display it, as in model-view-controller.",[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],{},"The subject and its observers are loosely coupled: each depends only on the other's interface.",[49,76,77],{},"Observers can be added and removed at any time.",[49,79,80],{},"One call from the subject reaches every observer, as a broadcast.",[66,82,84],{"id":83},"cons","Cons",[46,86,87,90,93],{},[49,88,89],{},"With many observers, notifying all of them can be slow.",[49,91,92],{},"The flow of the program is harder to follow, since the subject doesn't show who reacts to a change.",[49,94,95],{},"An observer that never unsubscribes keeps being called, and stays in memory as long as the subject does.",[27,97,99],{"id":98},"the-example","The example",[32,101,102],{},"The example is a tweet and its followers. A follower subscribes to a tweet, and when the tweet notifies its listeners, each follower prints a notification with the tweet's text.",[46,104,105,127,139,151,159],{},[49,106,107,114,115,118,119,122,123,126],{},[108,109,110],"strong",{},[111,112,113],"code",{},"Event",": the subject interface: ",[111,116,117],{},"subscribe",", ",[111,120,121],{},"unsubscribe"," and ",[111,124,125],{},"notifyToAll",".",[49,128,129,134,135,138],{},[108,130,131],{},[111,132,133],{},"Listener",": the observer interface, with a single ",[111,136,137],{},"notify(message)"," method.",[49,140,141,146,147,150],{},[108,142,143],{},[111,144,145],{},"Tweet",": the concrete subject. It keeps its text and a list of listeners, and ",[111,148,149],{},"notifyToAll()"," passes the text to each one.",[49,152,153,158],{},[108,154,155],{},[111,156,157],{},"Follower",": the concrete observer. It has a username and prints the message it receives.",[49,160,161,166],{},[108,162,163],{},[111,164,165],{},"Demo",": creates a follower and a tweet, subscribes the follower and sends the notification.",[32,168,169],{},"The tweet sends its text along with the call. This is the push model. In the pull model, observers get only a signal and ask the subject for what they need.",[27,171,173],{"id":172},"the-code","The code",[175,176,182],"pre",{"className":177,"code":178,"filename":179,"language":180,"meta":181,"style":181},"language-java shiki shiki-themes haytham-dark haytham-light","public interface Event {\n    void subscribe(Listener listener);\n    void unsubscribe(Listener listener);\n    void notifyToAll();\n}\n","Event.java","java","",[111,183,184,204,226,242,253],{"__ignoreMap":181},[185,186,189,193,196,200],"span",{"class":187,"line":188},"line",1,[185,190,192],{"class":191},"sVsk0","public",[185,194,195],{"class":191}," interface",[185,197,199],{"class":198},"sNwy7"," Event",[185,201,203],{"class":202},"sVG6I"," {\n",[185,205,207,210,214,217,219,223],{"class":187,"line":206},2,[185,208,209],{"class":191},"    void",[185,211,213],{"class":212},"sVz7n"," subscribe",[185,215,216],{"class":202},"(",[185,218,133],{"class":191},[185,220,222],{"class":221},"sWFPS"," listener",[185,224,225],{"class":202},");\n",[185,227,229,231,234,236,238,240],{"class":187,"line":228},3,[185,230,209],{"class":191},[185,232,233],{"class":212}," unsubscribe",[185,235,216],{"class":202},[185,237,133],{"class":191},[185,239,222],{"class":221},[185,241,225],{"class":202},[185,243,245,247,250],{"class":187,"line":244},4,[185,246,209],{"class":191},[185,248,249],{"class":212}," notifyToAll",[185,251,252],{"class":202},"();\n",[185,254,256],{"class":187,"line":255},5,[185,257,258],{"class":202},"}\n",[175,260,263],{"className":177,"code":261,"filename":262,"language":180,"meta":181,"style":181},"public interface Listener {\n    void notify(String message);\n}\n","Listener.java",[111,264,265,276,293],{"__ignoreMap":181},[185,266,267,269,271,274],{"class":187,"line":188},[185,268,192],{"class":191},[185,270,195],{"class":191},[185,272,273],{"class":198}," Listener",[185,275,203],{"class":202},[185,277,278,280,283,285,288,291],{"class":187,"line":206},[185,279,209],{"class":191},[185,281,282],{"class":212}," notify",[185,284,216],{"class":202},[185,286,287],{"class":191},"String",[185,289,290],{"class":221}," message",[185,292,225],{"class":202},[185,294,295],{"class":187,"line":228},[185,296,258],{"class":202},[175,298,301],{"className":177,"code":299,"filename":300,"language":180,"meta":181,"style":181},"import java.util.ArrayList;\nimport java.util.List;\n\npublic class Tweet implements Event {\n    private final String text;\n    private final List\u003CListener> listeners;\n\n    public Tweet(String text) {\n        this.text = text;\n        this.listeners = new ArrayList\u003C>();\n    }\n\n    @Override\n    public void subscribe(Listener listener) {\n        this.listeners.add(listener);\n    }\n\n    @Override\n    public void unsubscribe(Listener listener) {\n        this.listeners.remove(listener);\n    }\n\n    @Override\n    public void notifyToAll() {\n        this.listeners.forEach((listener -> listener.notify(text)));\n    }\n}\n","Tweet.java",[111,302,303,324,341,347,364,380,403,408,427,447,468,474,479,488,508,529,534,539,546,565,585,590,595,602,615,652,657],{"__ignoreMap":181},[185,304,305,308,311,313,316,318,321],{"class":187,"line":188},[185,306,307],{"class":191},"import",[185,309,310],{"class":191}," java",[185,312,126],{"class":202},[185,314,315],{"class":191},"util",[185,317,126],{"class":202},[185,319,320],{"class":191},"ArrayList",[185,322,323],{"class":202},";\n",[185,325,326,328,330,332,334,336,339],{"class":187,"line":206},[185,327,307],{"class":191},[185,329,310],{"class":191},[185,331,126],{"class":202},[185,333,315],{"class":191},[185,335,126],{"class":202},[185,337,338],{"class":191},"List",[185,340,323],{"class":202},[185,342,343],{"class":187,"line":228},[185,344,346],{"emptyLinePlaceholder":345},true,"\n",[185,348,349,351,354,357,360,362],{"class":187,"line":244},[185,350,192],{"class":191},[185,352,353],{"class":191}," class",[185,355,356],{"class":198}," Tweet",[185,358,359],{"class":191}," implements",[185,361,199],{"class":198},[185,363,203],{"class":202},[185,365,366,369,372,375,378],{"class":187,"line":255},[185,367,368],{"class":191},"    private",[185,370,371],{"class":191}," final",[185,373,374],{"class":191}," String",[185,376,377],{"class":221}," text",[185,379,323],{"class":202},[185,381,383,385,387,390,393,395,398,401],{"class":187,"line":382},6,[185,384,368],{"class":191},[185,386,371],{"class":191},[185,388,389],{"class":191}," List",[185,391,392],{"class":202},"\u003C",[185,394,133],{"class":191},[185,396,397],{"class":202},">",[185,399,400],{"class":221}," listeners",[185,402,323],{"class":202},[185,404,406],{"class":187,"line":405},7,[185,407,346],{"emptyLinePlaceholder":345},[185,409,411,414,416,418,420,422,425],{"class":187,"line":410},8,[185,412,413],{"class":191},"    public",[185,415,356],{"class":212},[185,417,216],{"class":202},[185,419,287],{"class":191},[185,421,377],{"class":221},[185,423,424],{"class":202},")",[185,426,203],{"class":202},[185,428,430,434,436,440,443,445],{"class":187,"line":429},9,[185,431,433],{"class":432},"sheII","        this",[185,435,126],{"class":202},[185,437,439],{"class":438},"s4Awn","text",[185,441,442],{"class":202}," =",[185,444,377],{"class":221},[185,446,323],{"class":202},[185,448,450,452,454,457,459,462,465],{"class":187,"line":449},10,[185,451,433],{"class":432},[185,453,126],{"class":202},[185,455,456],{"class":438},"listeners",[185,458,442],{"class":202},[185,460,461],{"class":191}," new",[185,463,464],{"class":191}," ArrayList",[185,466,467],{"class":202},"\u003C>();\n",[185,469,471],{"class":187,"line":470},11,[185,472,473],{"class":202},"    }\n",[185,475,477],{"class":187,"line":476},12,[185,478,346],{"emptyLinePlaceholder":345},[185,480,482,485],{"class":187,"line":481},13,[185,483,484],{"class":202},"    @",[185,486,487],{"class":191},"Override\n",[185,489,491,493,496,498,500,502,504,506],{"class":187,"line":490},14,[185,492,413],{"class":191},[185,494,495],{"class":191}," void",[185,497,213],{"class":212},[185,499,216],{"class":202},[185,501,133],{"class":191},[185,503,222],{"class":221},[185,505,424],{"class":202},[185,507,203],{"class":202},[185,509,511,513,515,517,519,522,524,527],{"class":187,"line":510},15,[185,512,433],{"class":432},[185,514,126],{"class":202},[185,516,456],{"class":438},[185,518,126],{"class":202},[185,520,521],{"class":212},"add",[185,523,216],{"class":202},[185,525,526],{"class":221},"listener",[185,528,225],{"class":202},[185,530,532],{"class":187,"line":531},16,[185,533,473],{"class":202},[185,535,537],{"class":187,"line":536},17,[185,538,346],{"emptyLinePlaceholder":345},[185,540,542,544],{"class":187,"line":541},18,[185,543,484],{"class":202},[185,545,487],{"class":191},[185,547,549,551,553,555,557,559,561,563],{"class":187,"line":548},19,[185,550,413],{"class":191},[185,552,495],{"class":191},[185,554,233],{"class":212},[185,556,216],{"class":202},[185,558,133],{"class":191},[185,560,222],{"class":221},[185,562,424],{"class":202},[185,564,203],{"class":202},[185,566,568,570,572,574,576,579,581,583],{"class":187,"line":567},20,[185,569,433],{"class":432},[185,571,126],{"class":202},[185,573,456],{"class":438},[185,575,126],{"class":202},[185,577,578],{"class":212},"remove",[185,580,216],{"class":202},[185,582,526],{"class":221},[185,584,225],{"class":202},[185,586,588],{"class":187,"line":587},21,[185,589,473],{"class":202},[185,591,593],{"class":187,"line":592},22,[185,594,346],{"emptyLinePlaceholder":345},[185,596,598,600],{"class":187,"line":597},23,[185,599,484],{"class":202},[185,601,487],{"class":191},[185,603,604,606,608,610,613],{"class":187,"line":5},[185,605,413],{"class":191},[185,607,495],{"class":191},[185,609,249],{"class":212},[185,611,612],{"class":202},"()",[185,614,203],{"class":202},[185,616,618,620,622,624,626,629,632,635,638,640,642,645,647,649],{"class":187,"line":617},25,[185,619,433],{"class":432},[185,621,126],{"class":202},[185,623,456],{"class":438},[185,625,126],{"class":202},[185,627,628],{"class":212},"forEach",[185,630,631],{"class":202},"((",[185,633,634],{"class":221},"listener ",[185,636,637],{"class":191},"->",[185,639,222],{"class":221},[185,641,126],{"class":202},[185,643,644],{"class":212},"notify",[185,646,216],{"class":202},[185,648,439],{"class":221},[185,650,651],{"class":202},")));\n",[185,653,655],{"class":187,"line":654},26,[185,656,473],{"class":202},[185,658,660],{"class":187,"line":659},27,[185,661,258],{"class":202},[175,663,666],{"className":177,"code":664,"filename":665,"language":180,"meta":181,"style":181},"public class Follower implements Listener {\n    private final String username;\n\n    public Follower(String username) {\n        this.username = username;\n    }\n\n    @Override\n    public void notify(String message) {\n        System.out.println(\"New notification to @\" + this.username + \" : \" + message);\n    }\n}\n","Follower.java",[111,667,668,683,696,700,716,731,735,739,745,763,805,809],{"__ignoreMap":181},[185,669,670,672,674,677,679,681],{"class":187,"line":188},[185,671,192],{"class":191},[185,673,353],{"class":191},[185,675,676],{"class":198}," Follower",[185,678,359],{"class":191},[185,680,273],{"class":198},[185,682,203],{"class":202},[185,684,685,687,689,691,694],{"class":187,"line":206},[185,686,368],{"class":191},[185,688,371],{"class":191},[185,690,374],{"class":191},[185,692,693],{"class":221}," username",[185,695,323],{"class":202},[185,697,698],{"class":187,"line":228},[185,699,346],{"emptyLinePlaceholder":345},[185,701,702,704,706,708,710,712,714],{"class":187,"line":244},[185,703,413],{"class":191},[185,705,676],{"class":212},[185,707,216],{"class":202},[185,709,287],{"class":191},[185,711,693],{"class":221},[185,713,424],{"class":202},[185,715,203],{"class":202},[185,717,718,720,722,725,727,729],{"class":187,"line":255},[185,719,433],{"class":432},[185,721,126],{"class":202},[185,723,724],{"class":438},"username",[185,726,442],{"class":202},[185,728,693],{"class":221},[185,730,323],{"class":202},[185,732,733],{"class":187,"line":382},[185,734,473],{"class":202},[185,736,737],{"class":187,"line":405},[185,738,346],{"emptyLinePlaceholder":345},[185,740,741,743],{"class":187,"line":410},[185,742,484],{"class":202},[185,744,487],{"class":191},[185,746,747,749,751,753,755,757,759,761],{"class":187,"line":429},[185,748,413],{"class":191},[185,750,495],{"class":191},[185,752,282],{"class":212},[185,754,216],{"class":202},[185,756,287],{"class":191},[185,758,290],{"class":221},[185,760,424],{"class":202},[185,762,203],{"class":202},[185,764,765,768,770,773,775,778,780,784,787,790,792,794,796,799,801,803],{"class":187,"line":449},[185,766,767],{"class":221},"        System",[185,769,126],{"class":202},[185,771,772],{"class":438},"out",[185,774,126],{"class":202},[185,776,777],{"class":212},"println",[185,779,216],{"class":202},[185,781,783],{"class":782},"sUOzB","\"New notification to @\"",[185,785,786],{"class":202}," +",[185,788,789],{"class":432}," this",[185,791,126],{"class":202},[185,793,724],{"class":438},[185,795,786],{"class":202},[185,797,798],{"class":782}," \" : \"",[185,800,786],{"class":202},[185,802,290],{"class":221},[185,804,225],{"class":202},[185,806,807],{"class":187,"line":470},[185,808,473],{"class":202},[185,810,811],{"class":187,"line":476},[185,812,258],{"class":202},[175,814,817],{"className":177,"code":815,"filename":816,"language":180,"meta":181,"style":181},"public class Demo {\n    public static void main(String[] args) {\n        Follower haythamasalama = new Follower(\"haythamsalsama\");\n        Tweet tweet = new Tweet(\"Welcome Friends!!\");\n        \n        tweet.subscribe(haythamasalama);\n        tweet.notifyToAll();\n    }\n}\n","Demo.java",[111,818,819,830,856,878,899,904,920,930,934],{"__ignoreMap":181},[185,820,821,823,825,828],{"class":187,"line":188},[185,822,192],{"class":191},[185,824,353],{"class":191},[185,826,827],{"class":198}," Demo",[185,829,203],{"class":202},[185,831,832,834,837,839,842,844,846,849,852,854],{"class":187,"line":206},[185,833,413],{"class":191},[185,835,836],{"class":191}," static",[185,838,495],{"class":191},[185,840,841],{"class":212}," main",[185,843,216],{"class":202},[185,845,287],{"class":191},[185,847,848],{"class":202},"[]",[185,850,851],{"class":221}," args",[185,853,424],{"class":202},[185,855,203],{"class":202},[185,857,858,861,864,867,869,871,873,876],{"class":187,"line":228},[185,859,860],{"class":191},"        Follower",[185,862,863],{"class":221}," haythamasalama ",[185,865,866],{"class":202},"=",[185,868,461],{"class":191},[185,870,676],{"class":212},[185,872,216],{"class":202},[185,874,875],{"class":782},"\"haythamsalsama\"",[185,877,225],{"class":202},[185,879,880,883,886,888,890,892,894,897],{"class":187,"line":244},[185,881,882],{"class":191},"        Tweet",[185,884,885],{"class":221}," tweet ",[185,887,866],{"class":202},[185,889,461],{"class":191},[185,891,356],{"class":212},[185,893,216],{"class":202},[185,895,896],{"class":782},"\"Welcome Friends!!\"",[185,898,225],{"class":202},[185,900,901],{"class":187,"line":255},[185,902,903],{"class":221},"        \n",[185,905,906,909,911,913,915,918],{"class":187,"line":382},[185,907,908],{"class":221},"        tweet",[185,910,126],{"class":202},[185,912,117],{"class":212},[185,914,216],{"class":202},[185,916,917],{"class":221},"haythamasalama",[185,919,225],{"class":202},[185,921,922,924,926,928],{"class":187,"line":405},[185,923,908],{"class":221},[185,925,126],{"class":202},[185,927,125],{"class":212},[185,929,252],{"class":202},[185,931,932],{"class":187,"line":410},[185,933,473],{"class":202},[185,935,936],{"class":187,"line":429},[185,937,258],{"class":202},[32,939,940,941,943],{},"Running ",[111,942,165],{}," prints:",[175,945,949],{"className":946,"code":948,"language":439,"meta":181},[947],"language-text","New notification to @haythamsalsama : Welcome Friends!!\n",[111,950,948],{"__ignoreMap":181},[952,953,954],"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 .sVz7n, html code.shiki .sVz7n{--shiki-default:#EDEDEF;--shiki-light:#0B0B0C}html pre.shiki code .sWFPS, html code.shiki .sWFPS{--shiki-default:#C4C4CC;--shiki-light:#3F3F46}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 .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 pre.shiki code .sUOzB, html code.shiki .sUOzB{--shiki-default:#9EC7FE;--shiki-light:#2873D1}",{"title":181,"searchDepth":206,"depth":206,"links":956},[957,958,959,963,964],{"id":29,"depth":206,"text":30},{"id":43,"depth":206,"text":44},{"id":63,"depth":206,"text":64,"children":960},[961,962],{"id":68,"depth":228,"text":69},{"id":83,"depth":228,"text":84},{"id":98,"depth":206,"text":99},{"id":172,"depth":206,"text":173},"The Observer pattern lets one object announce a change to every object that subscribed to it, without knowing who they are or what they do. Explained with a worked Java example of a tweet and its followers.","A tweet and its followers","md","Behavioral","lucide:bell",{},"\u002Flearn\u002Fdesign-patterns\u002Fobserver","---\ntitle: Observer\ngroup: Behavioral\nicon: lucide:bell\nsummary: 'One object announces a change, and every object that subscribed to it hears about it.'\ndescription: 'The Observer pattern lets one object announce a change to every object that subscribed to it, without knowing who they are or what they do. Explained with a worked Java example of a tweet and its followers.'\nexample: 'A tweet and its followers'\norder: 4\nsource: https:\u002F\u002Fgithub.com\u002FHaythamasalama\u002FdesignPattern\u002Ftree\u002Fmaster\u002Fsrc\u002FBehavioral\u002FObserver\n---\n\n## The idea\n\nOften several objects need to react when something happens to another object. When a tweet is posted, every follower should hear about it. The tweet could call each follower directly, but then it would need to know every kind of object that cares, and change whenever a new one appears.\n\nThe Observer pattern turns this around. The object being watched, the subject, keeps a list of observers. Observers subscribe to it and can unsubscribe at any time. When something happens, the subject goes through its list and calls the same method on each observer. All it knows about them is that they implement the observer interface.\n\nThis gives a one-to-many relationship with loose coupling. The subject doesn't know what its observers do, and you can add new kinds of observers without changing it.\n\n## When to use it\n\n- A change to one object should update others, and you don't know in advance how many or which ones.\n- You want objects to subscribe and unsubscribe while the program runs.\n- You are building events: a button click, a new message, a price change.\n- You want to keep a model separate from the views that display it, as in model-view-controller.\n\n## Pros and cons\n\n### Pros\n\n- The subject and its observers are loosely coupled: each depends only on the other's interface.\n- Observers can be added and removed at any time.\n- One call from the subject reaches every observer, as a broadcast.\n\n### Cons\n\n- With many observers, notifying all of them can be slow.\n- The flow of the program is harder to follow, since the subject doesn't show who reacts to a change.\n- An observer that never unsubscribes keeps being called, and stays in memory as long as the subject does.\n\n## The example\n\nThe example is a tweet and its followers. A follower subscribes to a tweet, and when the tweet notifies its listeners, each follower prints a notification with the tweet's text.\n\n- **`Event`**: the subject interface: `subscribe`, `unsubscribe` and `notifyToAll`.\n- **`Listener`**: the observer interface, with a single `notify(message)` method.\n- **`Tweet`**: the concrete subject. It keeps its text and a list of listeners, and `notifyToAll()` passes the text to each one.\n- **`Follower`**: the concrete observer. It has a username and prints the message it receives.\n- **`Demo`**: creates a follower and a tweet, subscribes the follower and sends the notification.\n\nThe tweet sends its text along with the call. This is the push model. In the pull model, observers get only a signal and ask the subject for what they need.\n\n## The code\n\n```java [Event.java]\npublic interface Event {\n    void subscribe(Listener listener);\n    void unsubscribe(Listener listener);\n    void notifyToAll();\n}\n```\n\n```java [Listener.java]\npublic interface Listener {\n    void notify(String message);\n}\n```\n\n```java [Tweet.java]\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class Tweet implements Event {\n    private final String text;\n    private final List\u003CListener> listeners;\n\n    public Tweet(String text) {\n        this.text = text;\n        this.listeners = new ArrayList\u003C>();\n    }\n\n    @Override\n    public void subscribe(Listener listener) {\n        this.listeners.add(listener);\n    }\n\n    @Override\n    public void unsubscribe(Listener listener) {\n        this.listeners.remove(listener);\n    }\n\n    @Override\n    public void notifyToAll() {\n        this.listeners.forEach((listener -> listener.notify(text)));\n    }\n}\n```\n\n```java [Follower.java]\npublic class Follower implements Listener {\n    private final String username;\n\n    public Follower(String username) {\n        this.username = username;\n    }\n\n    @Override\n    public void notify(String message) {\n        System.out.println(\"New notification to @\" + this.username + \" : \" + message);\n    }\n}\n```\n\n```java [Demo.java]\npublic class Demo {\n    public static void main(String[] args) {\n        Follower haythamasalama = new Follower(\"haythamsalsama\");\n        Tweet tweet = new Tweet(\"Welcome Friends!!\");\n        \n        tweet.subscribe(haythamasalama);\n        tweet.notifyToAll();\n    }\n}\n```\n\nRunning `Demo` prints:\n\n```text\nNew notification to @haythamsalsama : Welcome Friends!!\n```\n",{"title":22,"description":965},{"loc":971},"https:\u002F\u002Fgithub.com\u002FHaythamasalama\u002FdesignPattern\u002Ftree\u002Fmaster\u002Fsrc\u002FBehavioral\u002FObserver","learn\u002Fdesign-patterns\u002Fobserver","One object announces a change, and every object that subscribed to it hears about it.","9OrhgDGhToW08SwmL97drfrQ9OO-tJ7N8fPwxR6QwCs",[980,985,990,995,996,1001,1006,1011],{"path":981,"title":982,"icon":983,"summary":984,"order":188},"\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":986,"title":987,"icon":988,"summary":989,"order":206},"\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":991,"title":992,"icon":993,"summary":994,"order":228},"\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":971,"title":22,"icon":969,"summary":977,"order":244},{"path":997,"title":998,"icon":999,"summary":1000,"order":255},"\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":1002,"title":1003,"icon":1004,"summary":1005,"order":382},"\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":1007,"title":1008,"icon":1009,"summary":1010,"order":405},"\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":1012,"title":1013,"icon":1014,"summary":1015,"order":410},"\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":1017},"\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":1019},"\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":1021},"\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":1023},"\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":1025},"\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":1027},"\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":1029},"\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":1031},"\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":1033},"\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":1035},"\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":1037},"\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>",1793131416878]