您的位置:首页 > 其它

19使用推模式和拉模式实现电梯超重报警

2014-03-26 23:31 225 查看
当电梯超过最大承重800公斤,报警器报警。把电梯看成被观察者,报警器看成观察者。分别使用推模式和拉模式实现超重报警。

 

  推模式实现超重报警

被观察者在运行本身方法的时候,达到一定条件,就触发通知事件,把自己的状态"推"个观察者。

→把电梯看作是被观察者,当运行其TestWeight()方法时候,如果满足某种weight变量>800,就触发方法把自己的状态推给观察者。

 //被观察者


[code] public class Elevator : SubjectBase


{


private int weight;


private static string factory = "日立";


private static string area = "广州";


 




  protected virtual void OnMoreThanStandard(MoreThanStandardEventArgs e)


 {


base.Notify(e);


  }


 


  public void TestWeight()


 {


for (int i = 795; i <= 805; i++)


  {


 weight = i;


 if (weight > 800)


{


  MoreThanStandardEventArgs e = new MoreThanStandardEventArgs(weight,factory,area);


  OnMoreThanStandard(e);


 }


}


  }


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→Elevator把自己的状态信息封装成MoreThanStandardEventArgs类,推送给观察者。


 //观察者和被观察者之间传递的参数


[code] public class MoreThanStandardEventArgs


{


private int weight;


  private string factory;


  private string area;


 


  public MoreThanStandardEventArgs(int weight, string factory, string area)


 {


this.weight = weight;


this.factory = factory;


this.area = area;


  }


 


  public int Weight {get { return weight; }}


  public string Factory {get { return factory; }}


  public string Area {get { return area; }}


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→Elevator本身没有注册、注销、通知观察者的能力,所以需要继承有这些能力的基类SubjectBase。


//被观察者基类抽象类


[code] public abstract class SubjectBase : IObseervable


{


  private List<IObserver>  container = new List<IObserver>();


  public void Register(IObserver obj)


 {


container.Add(obj);


  }


 


  public void Unregister(IObserver obj)


 {


container.Remove(obj);


  }


 


  protected virtual void Notify(MoreThanStandardEventArgs e)


 {


foreach (IObserver observer in container)


  {


 observer.Update(e);


}


  }


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→而IObservalble的接口就注册和取消注册2个行为。


 //被观察者接口


[code] public interface IObseervable


{


  void Register(IObserver obj);


  void Unregister(IObserver obj);


 } 

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→观察者接口拿到被观察者推来的信息,做自己的事。


 //观察者接口


[code] public interface IObserver


{


  void Update(MoreThanStandardEventArgs e);


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→观察者就把状态信息显示出来


 //观察者


[code] public class Alarm : IObserver


{


  public void Update(MoreThanStandardEventArgs e)


 {


Console.WriteLine("嘀嘀嘀:来自{0}{1}的电梯最大承重800kg,目前重量为{2}",e.Area,e.Factory,e.Weight);


  }


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→主程序


 class Program


[code]{


  static void Main(string[] args)


 {


Elevator elevator = new Elevator();


Alarm alarm = new Alarm();


 


elevator.Register(alarm);


elevator.TestWeight();


Console.ReadKey();


  }


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

结果:





 

  拉模式实现超重报警   

观察者把被观察者拉进来作为方法参数,当被观察者在运行本身方法的时候,达到一定条件,就触发通知事件,并把自己传递给观察者方法。

 

→被观察者Elevator执行方法满足条件就触发通知


 //被观察者


[code] public class Elevator : SubjectBase


{


private int weight;


private static string factory = "日立";


private static string area = "广州";


 


  public int Weight {get { return weight; }}


  public string Factory {get { return factory; }}


  public string Area {get { return area; }}


 


  protected virtual void OnMoreThanStandard()


 {


base.Notify(this);


  }


 


  public void TestWeight()


 {


for (int i = 795; i <= 805; i++)


  {


 weight = i;


 if (weight > 800)


{


  OnMoreThanStandard();


 }


}


  }


 }


 

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→被观察者Elevator本身没有注册、取消注册、通知观察者的能力,需要继承拥有这些能力的SubjectBase。 


 //被观察者基类


[code] public abstract class SubjectBase : IObservable


{


  List<IObserver>  container = new List<IObserver>();


 


  public void Register(IObserver obj)


 {


container.Add(obj);


  }


 


  public void Unregister(IObserver obj)


 {


container.Remove(obj);


  }


 


  protected virtual void Notify(IObservable obj)


 {


foreach (IObserver observer in container)


  {


 observer.Update(obj);


}


  }


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→观察者调用自己拉进来的观察者对象获得其状态信息


 //观察者接口


[code] public interface IObserver


{


  void Update(IObservable sender);


 }


 


 //观察者


 public class Alarm : IObserver


{


  public void Update(IObservable sender)


 {


Elevator elevator = (Elevator)sender;


Console.WriteLine("嘀嘀嘀:来自{0}{1}的电梯最大承重800kg,目前重量为{2}", elevator.Area, elevator.Factory, elevator.Weight);


  }


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

→ 主程序


 class Program


[code]{


  static void Main(string[] args)


 {


Elevator elevator = new Elevator();


Alarm alarm = new Alarm();


 


elevator.Register(alarm);


elevator.TestWeight();


Console.ReadKey();


  }


 }

[/code]

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

结果:





 

  推模式和拉模式的区别

● 推模式的好处是按需供给:观察者需要什么状态信息,被观察者就把需要的状态信息封装起来推给观察者。缺点是需要创建封装的状态信息。

● 拉模式的好处是不需要创建推送给观察者的、封装状态的信息。缺点是把被观察者的属性和方法暴露给了被观察者。

 

而微软定义的委托EventHandler则很好解决了推和拉的问题,不仅可以拿到被观察者本身,同时可以拿到观察者的状态信息:

public delegate void EventHandler(object sender, EventArgs e)


.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

参考资料:

《.NET之美》--张子阳,感谢写了这么好的书!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: