题目1:几个同事为了在上班期间偷偷看休息,做点其他的事情,就和小秘偷偷联系了一下,如果老板回来了,就麻烦小秘偷偷通知一声,这样方便大家及时变更自己的工作状态。
分析:
根据题目分析,首先明确,肯定会有两个类:小秘类和同事类,分别描述与记录两种类型的人和行为。
需要注意的是:小秘与同事构建联系的时候,一个小秘可能对应多位同事,所以这时需要利用List<>。
实现:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Secretary lady = new Secretary(); 6 StockObserver num1 = new StockObserver("A", lady); 7 StockObserver num2 = new StockObserver("B", lady); 8 9 lady.Attach(num1);10 lady.Attach(num2);11 12 lady.SecretAction="boss is back";13 lady.Notify();14 15 Console.Read();16 }17 }18 19 ///20 /// 小秘21 /// 1.记下需要联系的同事们List 26 class Secretary27 {28 IList22 /// 2.增加需要联系的人员23 /// 3.减少联系人员(有可能没有通知到,有可能人员辞职等)24 /// 4.秘密通知同事,老板回来了25 /// stockOb = new List ();29 private string action;30 31 public string SecretAction32 {33 get34 {35 return action;36 }37 38 set39 {40 action = value;41 }42 }43 44 //增加需要联系的人员45 public void Attach(StockObserver ob)46 {47 stockOb.Add(ob);48 }49 50 //减少需要联系的人员51 public void Detach(StockObserver ob)52 {53 stockOb.Remove(ob);54 }55 56 //小秘通知了同事后,同事赶紧自行更改工作状态57 public void Notify()58 {59 foreach (StockObserver o in stockOb)60 o.Update();61 }62 }63 64 /// 65 /// 看股票的同事66 /// 1.联系小秘,和小秘保持良好关系67 /// 2.根据小秘的偷偷通知修改自己的工作状态68 /// 69 class StockObserver70 {71 private string name;72 private Secretary sec;73 74 public StockObserver(string name,Secretary sec)75 {76 this.name = name;77 this.sec = sec;78 }79 public void Update()80 {81 Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sec.SecretAction, name);82 }83 }
题目2:由于同事们人数众多,所以大家休闲的方式并不一致。
分析:
同事们的休闲方式不同,他们彼此之间存在共同点与不同点。
他们的共同点在于都需要与小秘联系且更新工作状态,同时他们的不同点也在于更新工作状态。
所以相同点就不需要在子类中赘述,所以通过抽象类来将不同的方法设为抽象即可。
实现:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Secretary lady = new Secretary(); 6 StockObserver num1 = new StockObserver("A", lady); 7 NBAObserver num2 = new NBAObserver("B", lady); 8 9 lady.Attach(num1); 10 lady.Attach(num2); 11 12 lady.SecretAction = "boss is back"; 13 lady.Notify(); 14 15 Console.Read(); 16 } 17 } 18 19 ///20 /// 小秘 21 /// 1.记下需要联系的同事们List 26 class Secretary 27 { 28 IList22 /// 2.增加需要联系的人员 23 /// 3.减少联系人员(有可能没有通知到,有可能人员辞职等) 24 /// 4.秘密通知同事,老板回来了 25 /// observers = new List (); 29 private string action; 30 31 public string SecretAction 32 { 33 get 34 { 35 return action; 36 } 37 38 set 39 { 40 action = value; 41 } 42 } 43 44 //增加需要联系的人员 45 public void Attach(Observers ob) 46 { 47 observers.Add(ob); 48 } 49 50 //减少需要联系的人员 51 public void Detach(Observers ob) 52 { 53 observers.Remove(ob); 54 } 55 56 //小秘通知了同事后,同事赶紧自行更改工作状态 57 public void Notify() 58 { 59 foreach (Observers o in observers) 60 o.Update(); 61 } 62 } 63 64 /// 65 /// 观察者类 66 /// 抽象类 67 /// 偷偷玩的同事的状态都不同,他们的共同点就是1.与小秘联系,2.更新工作状态 68 /// 不同点在于更新状态前不同,所以更新工作状态设置为抽象方法即可 69 /// 70 abstract class Observers 71 { 72 protected string name; 73 protected Secretary sec; 74 75 public Observers(string name,Secretary sec) 76 { 77 this.name = name; 78 this.sec = sec; 79 } 80 81 public abstract void Update(); 82 } 83 84 85 ///86 /// 看股票的同事 87 /// 继承于观察者类 88 /// 根据小秘的偷偷通知修改自己的工作状态 89 /// 90 class StockObserver:Observers 91 { 92 public StockObserver(string name, Secretary sec) 93 : base(name, sec) 94 { 95 } 96 97 public override void Update() 98 { 99 Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sec.SecretAction,name);100 }101 }102 103 ///104 /// 看NBA节目的同事105 /// 继承于观察者类106 /// 根据小秘的偷偷通知修改自己的工作状态107 /// 108 class NBAObserver : Observers109 {110 public NBAObserver(string name, Secretary sec) 111 : base(name, sec)112 {113 }114 115 public override void Update()116 {117 Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sec.SecretAction, name);118 }119 }
题目3:如果小秘突然有事情变得特别忙的时候,就没有了通知者,而此刻老板突然回来了,所以老板本身就变成了临时的通知者。
分析:
老板本身变成了临时的通知者,虽然这个故事很不幸,但是客观分析,此刻老板的作用于小秘是一样的,所以老板应该和小秘继承于同一种父类。
由于老板需要与观察者联系,而此刻的观察者已是抽象类,所以老板的父类不能再为抽象类了。
原因如下:
故此,老板和小秘只能通过接口来实现了。
实现:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Boss boss = new Boss(); 6 7 8 Secretary lady = new Secretary(); 9 StockObserver num1 = new StockObserver("A", lady); 10 NBAObserver num2 = new NBAObserver("B", lady); 11 12 //lady没来的及通知两位同事 13 lady.Detach(num1); 14 lady.Detach(num2); 15 16 //现在的通知者就变成了boss 17 boss.Attach(num1); 18 boss.Attach(num2); 19 20 //num2没有看见boss回来,所以boss没来的及通知他 21 boss.Detach(num2); 22 23 boss.SecretAction = "boss is back"; 24 boss.Notify(); 25 26 Console.Read(); 27 } 28 } 29 30 ///31 /// 通知者的接口 32 /// 不能用抽象类 33 /// 34 interface Subject 35 { 36 void Attach(Observers ob); 37 void Detach(Observers ob); 38 void Notify(); 39 string SecretAction 40 { 41 get;set; 42 } 43 } 44 45 class Boss : Subject 46 { 47 IListobservers = new List (); 48 private string action; 49 50 public string SecretAction 51 { 52 get 53 { 54 return action; 55 } 56 57 set 58 { 59 action = value; 60 } 61 } 62 63 //增加需要联系的人员 64 public void Attach(Observers ob) 65 { 66 observers.Add(ob); 67 } 68 69 //减少需要联系的人员 70 public void Detach(Observers ob) 71 { 72 observers.Remove(ob); 73 } 74 75 //大家看见boss回来后,同事赶紧自行更改工作状态 76 public void Notify() 77 { 78 foreach (Observers o in observers) 79 o.Update(); 80 } 81 } 82 83 /// 84 /// 小秘:继承于接口 85 /// 1.记下需要联系的同事们List 90 class Secretary:Subject 91 { 92 IList86 /// 2.增加需要联系的人员 87 /// 3.减少联系人员(有可能没有通知到,有可能人员辞职等) 88 /// 4.秘密通知同事,老板回来了 89 /// observers = new List (); 93 private string action; 94 95 public string SecretAction 96 { 97 get 98 { 99 return action;100 }101 102 set103 {104 action = value;105 }106 }107 108 //增加需要联系的人员109 public void Attach(Observers ob)110 {111 observers.Add(ob);112 }113 114 //减少需要联系的人员115 public void Detach(Observers ob)116 {117 observers.Remove(ob);118 }119 120 //小秘通知了同事后,同事赶紧自行更改工作状态121 public void Notify()122 {123 foreach (Observers o in observers)124 o.Update();125 }126 }127 128 /// 129 /// 观察者类130 /// 抽象类131 /// 偷偷玩的同事的状态都不同,他们的共同点就是1.与小秘联系,2.更新工作状态132 /// 不同点在于更新状态前不同,所以更新工作状态设置为抽象方法即可133 /// 134 abstract class Observers135 {136 protected string name;137 protected Secretary sec;138 139 public Observers(string name, Secretary sec)140 {141 this.name = name;142 this.sec = sec;143 }144 145 public abstract void Update();146 }147 148 149 ///150 /// 看股票的同事151 /// 继承于观察者类152 /// 根据小秘的偷偷通知修改自己的工作状态153 /// 154 class StockObserver : Observers155 {156 public StockObserver(string name, Secretary sec)157 : base(name, sec)158 {159 }160 161 public override void Update()162 {163 Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sec.SecretAction, name);164 }165 }166 167 ///168 /// 看NBA节目的同事169 /// 继承于观察者类170 /// 根据小秘的偷偷通知修改自己的工作状态171 /// 172 class NBAObserver : Observers173 {174 public NBAObserver(string name, Secretary sec)175 : base(name, sec)176 {177 }178 179 public override void Update()180 {181 Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sec.SecretAction, name);182 }183 }
附:
实现:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Boss boss = new Boss(); 6 Secretary lady = new Secretary(); 7 8 StockObserver num1 = new StockObserver("A", boss); 9 NBAObserver num2 = new NBAObserver("B", boss); 10 11 //将“看股票”的“关闭股票程序”方法和“看NBA者”的“关闭NBA直播”的方法 12 //挂钩到老板的“更新”上,也就是将两种不同类的不同方法委托给老板类的更新了。 13 boss.Update += new EventHandler(num1.CloseStockMarket); 14 boss.Update += new EventHandler(num2.CloseNBADirectSeeding); 15 16 boss.SecretAction = "boss is back"; 17 boss.Notify(); 18 19 Console.Read(); 20 } 21 } 22 23 ///24 /// 通知者的接口 25 /// 不能用抽象类 26 /// 现在抽象通知者由于不下网依赖抽象观察者,所以“增加”和“减少”的方法就没有必要了 27 /// 28 interface Subject 29 { 30 void Notify(); 31 string SecretAction 32 { 33 get; set; 34 } 35 } 36 37 ///38 /// 委托就是一种引用方法的类型。 39 /// 一旦为委托分配了方法,委托将于该方法具有完全相同的行为 40 /// 委托方法的使用可以像任何其他方法一样,具有参数和返回值。 41 /// 委托可以看做是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数 42 /// 43 /// 一个委托可以搭载多个方法,所有的方法被依次唤起 44 /// 最重要的是,它可以使得委托对象所搭载的方法并不需要属于同一个类 45 /// 46 /// 委托对象所搭载的所有方法必须具有相同的原型和形式,也就是有相同的参数列表和返回值类型 47 /// 48 delegate void EventHandler(); //委托 49 50 class Boss : Subject 51 { 52 public event EventHandler Update; 53 54 private string action; 55 56 public string SecretAction 57 { 58 get 59 { 60 return action; 61 } 62 63 set 64 { 65 action = value; 66 } 67 } 68 69 //大家看见boss回来后,同事赶紧自行更改工作状态 70 public void Notify() 71 { 72 Update(); 73 } 74 } 75 76 ///77 /// 小秘:继承于接口 78 /// 1.记下需要联系的同事们List 83 class Secretary : Subject 84 { 85 public event EventHandler Update; 86 87 private string action; 88 89 public string SecretAction 90 { 91 get 92 { 93 return action; 94 } 95 96 set 97 { 98 action = value; 99 }100 }101 102 103 //小秘通知了同事后,同事赶紧自行更改工作状态104 public void Notify()105 {106 Update();107 }108 }109 110 ///79 /// 2.增加需要联系的人员 80 /// 3.减少联系人员(有可能没有通知到,有可能人员辞职等) 81 /// 4.秘密通知同事,老板回来了 82 /// 111 /// 看股票的同事112 /// 根据小秘的偷偷通知修改自己的工作状态113 /// 114 class StockObserver 115 {116 private string name;117 private Subject sub;118 119 public StockObserver(string name,Subject sub)120 {121 this.name = name;122 this.sub = sub;123 }124 125 public void CloseStockMarket()126 {127 Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SecretAction, name);128 }129 }130 131 ///132 /// 看NBA节目的同事133 /// 根据小秘的偷偷通知修改自己的工作状态134 /// 135 class NBAObserver 136 {137 private string name;138 private Subject sub;139 140 public NBAObserver(string name,Subject sub)141 {142 this.name = name;143 this.sub = sub;144 }145 146 public void CloseNBADirectSeeding()147 {148 Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SecretAction, name);149 }150 }
总结:
观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己。
观察者模式所做的工作其实就是在接触耦合。让耦合的双方依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响另一边的变化。
委托:就是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值。委托可以看作是对函数的抽象,是函数的‘类’,委托的实例将代表一个具体的函数。
一个委托可以搭载多个方法,所有方法被依次唤起。
委托对象所搭载的方法并不需要属于同一个类。
注:文中所有代码及知识点均来自于《大话设计模式》,本人属于边学边看边敲代码边总结的阶段。