在日常生活中,我们有很多这样的使用示例。例如我订阅了某个公众号,当公众号进行了更新之后,所有的订阅者都能收到消息。我对朋友圈的某条动态进行了评论,当有新评论增加时,我也会收到相应的动态更新。
首先在这里说明一下,go 中并没有像java 那样,从编程语言层面对设计模式进行支持。因此我们主要还是从代码语义的角度上来进行理解。如果想要严格的理解观察者模式,建议可以结合实际应用场景查看一下java的Demo。
package observer
type Observer interface {
Update(observable *Observable)
}
type Observable struct {
content string
obs []Observer
}
func NewObservable() *Observable {
return &Observable{obs: make([]Observer, 0)}
}
//AddObserver 向被观察者的订阅集合中添加观察者
//需要是线程安全的
//如果被观察者已经存在,则不添加
func (o *Observable) AddObserver(observer Observer) {
o.obs = append(o.obs, observer)
}
func (o *Observable) Notify() {
for _, observer := range o.obs {
observer.Update(o)
}
}
// 更新被订阅者的内容
func (o *Observable) UpdateContent(content string) {
o.content = content
}
package observer
import "fmt"
type Subscriber struct {
name string
}
func NewSubscriber(name string) *Subscriber {
return &Subscriber{name: name}
}
func (s *Subscriber) Update(observable *Observable) {
fmt.Printf("%s receive %s \n", s.name, observable.content)
}
package observer
func ExampleObserver() {
observable := NewObservable()
subscriber1 := NewSubscriber("hello1")
subscriber2 := NewSubscriber("hello2")
observable.AddObserver(subscriber1)
observable.AddObserver(subscriber2)
observable.UpdateContent("world")
observable.Notify()
// Output:
// hello1 receive worl1d
// hello2 receive world
}
package tech.selinux.design.pattern.behavioral.observer;
import java.util.Observable;
/** 公众号 */
public class OfficialAccounts extends Observable {
private String accountsName;
public OfficialAccounts(String accountsName) {
this.accountsName = accountsName;
}
public String getAccountsName() {
return accountsName;
}
// 代表状态发生改变
public void publishArticle(OfficialAccounts accounts, Article article) {
System.out.println(article.getTitle() + " on " + accounts.getAccountsName());
setChanged();
notifyObservers(article);
}
}
package tech.selinux.design.pattern.behavioral.observer;
public class Article {
private String title;
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
package tech.selinux.design.pattern.behavioral.observer;
import java.util.Observable;
import java.util.Observer;
/** 对于用户来说,观察的是公众号 观察者是 user,被观察者是 offical accounts */
public class User implements Observer {
private String nickName;
public User(String nickName) {
this.nickName = nickName;
}
@Override
public void update(Observable o, Object arg) {
OfficialAccounts accounts = (OfficialAccounts) o;
Article article = (Article) arg;
StringBuilder sb = new StringBuilder();
sb.append("用户名:")
.append(nickName)
.append(": \n")
.append("公众号 :")
.append(accounts.getAccountsName())
.append("\n")
.append("文章:")
.append(article.getTitle())
.append("\n");
System.out.println(sb.toString());
}
}
package tech.selinux.design.pattern.behavioral.observer;
public class Test {
public static void main(String[] args) {
OfficialAccounts accounts = new OfficialAccounts("Linux 中国");
User user = new User("PegasusMeteor");
accounts.addObserver(user);
User user1 = new User("Pegasus");
accounts.addObserver(user1);
Article article = new Article();
article.setTitle("Linux 未来趋势");
article.setContent("一片大好");
accounts.publishArticle(accounts, article);
}
}
补充另一个版本的Java/Scala Demo 以及源码解析