对于观察者模式还不是特别大额理解,现在那么静静下心来好好的整理了一下。
自己理解搞这么多的设计模式到底是干什么? 解耦和模块化。试着想象,现在很吊的滴滴打车,曾经出现了很多的黑科技优惠券,不就是由于发展太快,解耦处理不好,出现了很多的‘黑科技’。(刚开始写,表达能力不是很强,后期我会慢慢的优化的。)
首先
观察者模式要做到
- 开放-封闭原则(修改原有的代码就代表不好)。
- 依赖倒转原则(应该让程序都依赖抽象,而不是相互依赖)。
让耦合的双方都依赖于抽象,而不是依赖于具体,从而使各自的变化都不会影响到另一边的变化。
到底观察者模式是什么样子的呢?
用一张图来解释观察者模式
代码来源(书籍):大话设计模式
//Subject类,可翻译为主题或抽象通知者,一般用一个抽象类或一个接口实现。它把所有对观察者对象的引用保存在一个聚集里面,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以拉回和删除观察者对象。
public abstract class Subject
{
private List<Observer> observers = new ArrayList<Observer>();
public void attach(Observer observer)
{
observers.add(observer);
}
public void detach(Observer observer)
{
observers.remove(observer);
}
public void announce()
{
for (Observer obj : observers)
{
obj.update();
}
}
}
//Observer类,抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。抽象观察者一般用一个抽象类或者一个接口实现。更新接口通常包含一个update()方法,这个方法叫做更新方法。
public abstract class Observer
{
public abstract void update();
}
//ConcreteSubject类,叫做具体主题或具体通知者,将有关状态存入具体观察者对象,在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色通常用一个具体子类实现。
public class ConcreteSubject extends Subject
{
// 具体被观察者状态
private String subjectState;
public String getSubjectState()
{
return subjectState;
}
public void setSubjectState(String subjectState)
{
this.subjectState = subjectState;
}
}
//ConcreteObserver类,具体观察者,实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态相协调。具体观察者角色可以保存一个指向具体主题对象的引用。具体观察者角色通常用一个具体子类实现。
public class ConcreteObserver extends Observer
{
private String name;
private String observerState;
private ConcreteSubject subject;
public ConcreteObserver(String name, ConcreteSubject subject)
{
this.name = name;
this.subject = subject;
}
public void update()
{
observerState = subject.getSubjectState();
System.out.println("观察者" + name + "的新状态是" + observerState);
}
public ConcreteSubject getSubject()
{
return subject;
}
public void setSubject(ConcreteSubject subject)
{
this.subject = subject;
}
}
//客户端代码
public class Main
{
public static void main(String[] args)
{
ConcreteSubject s = new ConcreteSubject();
s.attach(new ConcreteObserver("X", s));
s.attach(new ConcreteObserver("Y", s));
s.attach(new ConcreteObserver("Z", s));
s.setSubjectState("ABC");
s.announce();
}
}
结果显示:
观察者X的新状态是ABC
观察者Y的新状态是ABC
观察者Z的新状态是ABC
但是这样的话,抽象通知者还是依赖观察者
万一没有抽象观察者这样的接口,那么我们的观察者模式还是完成不了
用委托来解决
EventHandler(事件处理程序)
用委托的方式来进行通知每个具体的观察者的不同的updata的处理方法。
但是委托也是有前提的,那么就是委托对象所搭载的所有的方法必须具有相同的原型和形式,也就是拥有相同的返回值类型和参数列表
代码来源(书籍):大话设计模式
//看股票的同事
class StockObserver
{
private string name;
private Subject sub;
public StockObserver(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
//关闭股票行情
public void CloseStockMarket()
{
Console.WriteLine("{0} {1} 关闭股票行情,继续工作!", sub.SubjectState, name);
}
}
//看NBA的同事
class NBAObserver
{
private string name;
private Subject sub;
public NBAObserver(string name, Subject sub)
{
this.name = name;
this.sub = sub;
}
//关闭NBA直播
public void CloseNBADirectSeeding()
{
Console.WriteLine("{0} {1} 关闭NBA直播,继续工作!", sub.SubjectState, name);
}
}
//抽象通知者由于不希望依赖于抽象观察者,所以增加和减少的就没有必要了,抽象观察者已经不存在了,通知者接口如下
//通知者接口
interface Subject
{
void Notify();
string SubjectState
{
get;
set;
}
}
//事件处理程序的委托
delegate void EventHandler();
//老板类和前台秘书类
class Secretary : Subject
{
//声明一事件Update,类型为委托EventHandler
public event EventHandler Update;
private string action;
public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
class Boss : Subject
{
//声明一事件Update,类型为委托EventHandler
public event EventHandler Update;
private string action;
public void Notify()
{
Update();
}
public string SubjectState
{
get { return action; }
set { action = value; }
}
}
//客户端代码
class Program
{
static void Main(string[] args)
{
//老板胡汉三
Boss huhansan = new Boss();
//看股票的同事
StockObserver tongshi1 = new StockObserver("魏关姹", huhansan);
//看NBA的同事
NBAObserver tongshi2 = new NBAObserver("易管查", huhansan);
huhansan.Update += new EventHandler(tongshi1.CloseStockMarket);
huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding);
//老板回来
huhansan.SubjectState = "我胡汉三回来了!";
//发出通知
huhansan.Notify();
Console.Read();
}
}
运行结果:
老板回来了! 魏关姹关闭股票行情,继续工作!
老板回来了! 易管查关闭股票行情,继续工作!