魔兽世界6.2 超远视角:observer模式感悟(目的是松耦合)——循序渐进让世界如此美妙
来源:百度文库 编辑:九乡新闻网 时间:2024/07/14 02:22:54
不知不觉已经进入了设计模式璀璨的迷宫,早先偶然进入,it is so far that I can't understanding anthing .最近的项目应用和书上讲解的对比,昨天有偶然看到了李建忠老师的讲座,感觉自己开始真正成为了一个淘金者,而这条路的方向看似慢慢明朗起来。
李建忠最鲜明的主张是,设计模式是一种结果,而不是要去套用的规则。所以讲座从我们最常规的思维开始,逐步演化,让循序渐进在此充发挥了他的作用。感受非常深刻!也很感动。
观察者模式的存在的必要:
一个对象(目标对象)的状态发生改变,所有的依赖对象(观察者对象)都将得到通知。如果这样的依赖关系过于紧密,将使软件不能很好地抵御变化。
动机:
依赖抽象,实现软件体系结构松耦合
手段:利用面向对象,形成稳定的依赖
原则:依赖倒置:具体细节依赖抽象,不稳定依赖稳定
意图:
得到一对多的依赖关系,当一个对象的状态发生改变,依赖他的对象得到统统自动更新
要点:
独立地改变(扩展、继承接口)目标和观察者
接口概念:1.稳定;2.表达了契约合同,不一定用Inerface表现
事件和observer模式的关系:
事件中所使用的程序接口(用委托来实现),
委托比接口更加松耦合
委托(约定)要求:参数类型和返回值类型一致就可以
接口要求:方法名称也必须相同
委托将一些功能实现了,例如add,用+=实现了;遍历,隐含实现了;
从紧耦合到松耦合的演化:(自然的未经设计模式的代码)
public class BandAccount
{
Emailer emailer;
Mobile mobile;
public void withdraw(int data)
{
//...
emailer.SendEmail(userEmail);
mobile.SendNotification(phoneNumber);
}
}
public class Emailer
{
//希望通知到用户帐户emil
//发送通知。让自己得到更新
public void SendEmail(sting userEmail)//未将参数提取出来
{
//..
}
}
public class Mobile
{
//发送通知。让自己得到更新
public void SendNotification(string phoneNumber) //未将参数提取出来
{
//..
}
}
第一步:分化B
public class UserAccountArgs //用户信息类,这个类的信息将用作参数传递,args将是一个数组
{
public string moble;
public string email;
public UserAccountArgs()
{
}
}
public class BandAccount //A还没有分化
{
//一对一依赖关系-------------------
IAccountObserver emailer; //弱依赖关系
public void Withdraw(int data)
{
//...
UserAccountArgs args = new UserAccountArgs();//构造参数
//...
args.email = data // 此处将args的email属性赋值,没有这句,实现不了
emailer.Update(args);
}
}
Mobile mobile = new Mobile();
Email email = new Email();
public void withdraw(UserAccountArgs args) //传递的是参数和接口相同,实现了真正的参数抽象化
{
mobile.Update(args);
email.Update (args);
}
//------------------------------------
public interface IAccountObserver
{
void Update(UserAccountArgs args); //args中包含了用户信息,例如用户手机号,email地址
//提取出了方法和参数
}
public class Emailer : IAccountObserver
{
//希望通知到用户帐户emil
//发送通知。让自己得到更新
public void Update(UserAccountArgs args) //将参数提取出来
{
//..
string ToAddress = args.ToAddress; //参数具体传入
}
}
public class Mobile : IAccountObserver
{
//发送通知。让自己得到更新
public void Update(UserAccountArgs args) //将参数提取出来
{
//..
string mobileNumber = args.MobileNumber; //参数具体传入
}
}
分化A
public abstract class Subject
{
// ArrayList
ArrayList observerList = new ArrayList(); //此处的概念是可变长度的数组,.net中用这种写法
protected virtual void Notify(UserAccoutArgs args)
{
//...
UserAccountArgs args = new UserAccountArgs();//构造参数
//...
foreach (IAccountObserver observer in observerList)
{
observer.Update(args); //对每一个对象进行更新
}
}
public void AddObserver(IAccountObserver observer)
{
observerList.add(observer);
}
public void RemoveObserver(IAccountObserver observer)
{
observerList.Remove(observer);
}
}
public class BandAccount : Subject // 如果需要改变,就扩展
{
public void Withdraw(UserAccountArgs args)
{
//...
Notify(args);//对每一个对象进行更新
}
}
--------------------------------------------------------------------------
流程调用:
UserAccountArgs args = new UserAccountArgs();//参数传入
args.moble = "234";
args .email = "wangshiying1971@163.com";
BandAccount bankAccount = new BandAccount();
bankAccount.withdraw(args);
实现了订阅功能(观察者模式)的流程调用
思路,加入了
- 接口实例化到实现类
- 订阅过程(用到了可变长度数组ArrayList 的概念,订阅过程,就是向数组传递参数的过程)
UserAccountArgs args = new UserAccountArgs(); //参数传入
args.moble = "234";
args.email = "wangshiying1971@163.com";
IAccountObserver mobile = new Mobile();//接口实例化到实现类
IAccountObserver email = new Email();//接口实例化到实现类
bankAccount.AddObserver(mobile);//将实现类加入到数组——订阅过程
bankAccount.AddObserver(email);//将实现类加入到数组——订阅过程
BandAccount bankAccount = new BandAccount();
bankAccount.withdraw(args);
项目联想:工作中的那个用户对象,老板要加上身价等级。
分析:如果修改用户类,将会修改类的字段、属性、显示方法等。类似的改变今后还会有很多。
1.身价等级、2.用户自定义等级、3.约会等级这三个等级中,1和3对应,只是表现不同,1表现的是账户的余额-等级的对应关系,得到的结果是等级,3表现的是等级-花费金额,目的为了得到金额。
这三个需求,都是等级和金额对应关系这个对象的不同属性和方法。
与等级相关的类视图