观察者模式(Observer Patten)
观察者模式的定义:观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新
考虑到如下一个场景,记者每次获得独家新闻,都需要通知人民日报和新华日报,Hi,i have a new message!
public class SpecificRepoter {
private PeopleDaily pd;
private XinHuaDaily xd;
private String msg;
public Repoter(){
this.pd = new PeopleDaily();
this.xd = new XinhuaDaily();
}
public void gotNewNews(String msg){
this.msg = msg;
}
public void notifyNewspaperOffice(){
pd.update(msg);
xd.update(msg);
}
}
public class XinHuaDaily {
public void update(String message){
System.out.println("XinHua Daily got the new news!");
}
}
public class PeopleDaily {
public void update(String message){
System.out.println("People Daily got the new news!");
}
}
由于记者和报社之间的合约关系由记者来维护,维护方式为:和记者签订合同的报社作为记者的属性,也即具体报社类和记者类紧耦合,故合约关系的变化必然导致记者类的变化:
现在记者和人民日报的合约到期,同时和环球时报签订了新合约
顺承前面的设计方式,必须要修改记者类以适应合约关系的改变:
public class SpecificRepoter {
private XinHuaDaily xd;
private GlobalTimes gt;
private String msg;
public Repoter(){
this.xd = new XinHuaDaily();
this.gt = new GlobalTimes();
}
public void gotNewNews(String msg){
this.msg = msg;
}
public void notifyTheNewspaperOffice(){
xd.update(msg);
gt.update(msg);
}
}
public class GlobalTimes {
public void update(String message){
System.out.println("Global Times got the new news!");
}
}
显然这种设计的可扩展性很低,本质原因是记者类和具体报社类紧耦合
要提高程序的扩展性,则要从降低记者类和具体报社类的耦合度来下手:
设计一:
1,抽象出记者接口和报社抽象类,针对接口编程
2,记者与报社之间的合约关系不再通过记者组合具体报社类来维护。设计一个List<NewspaperOffice>来保存和记者签订合同的报社(本质原则也是封装可变化部分,但只是封装至一个List属性中,而没有单独封装至一个类中,不像设计二那么彻底),记者将不和任何特定的报社类相耦合
public interface Repoter {
public void registerNewspaperOffice(NewspaperOffice no);
public void removeNewspaperOffice(NewspaperOffice no);
public void notifyNewspaperOffice();
}
public class SpecificRepoter implements Repoter {
private String msg;
private List<NewspaperOffice> relation;
public SpecificRepoter(){
relation = new ArrayList<NewspaperOffice>();
}
public void registerNewspaperOffice(NewspaperOffice no) {
if(!relation.contains(no)){
relation.add(no);
}
}
public void removeNewspaperOffice(NewspaperOffice no) {
if(relation.contains(no)){
relation.remove(no);
}
}
public void notifyNewspaperOffice() {
if(null != relation && relation.size()>0){
for(NewspaperOffice no : relation){
no.update(this.msg);
}
}
}
public void getNewNews(String msg){
this.msg = msg;
notifyNewspaperOffice();
}
}
public abstract class NewspaperOffice {
protected Repoter repoter;
protected String newMsg;
public void register(){
repoter.registerNewspaperOffice(this);
}
public void remove(){
repoter.removeNewspaperOffice(this);
}
public abstract void update(String newMsg);
}
public class PeopleDaily extends NewspaperOffice{
public PeopleDaily(Repoter repoter){
this.repoter = repoter;
}
public void update(String newMsg) {
this.newMsg = newMsg;
System.out.println("People Daily got "+newMsg);
}
}
具体报社类设计拥有register()和remove()方法以提高使用时的灵活性,当然这不是必要的
无论合约关系如何变化,SpecificReport类都不需要重新设计修改,相当方便
public class Test {
public static void main(String[] args){
Repoter repoter = new SpecificRepoter();
NewspaperOffice n1 = new GlobalTimes(repoter);
NewspaperOffice n2 = new XinHuaDaily(repoter);
NewspaperOffice n3 = new PeopleDaily(repoter);
n1.register();
n2.register();
repoter.registerNewspaperOffice(n3);
repoter.getNewNews("news coming!");
n3.remove();
repoter.removeNewspaperOffice(n2);
repoter.getNewNews("another news coming!");
}
}
Global Times got news coming! XinHua Daily got news coming! People Daily got news coming! Global Times got another news coming!
总结一下:
我们再来看看观察者模式:
当然具体实现方式上可以有多种变化
设计二,将记者和报社的合约关系独立出去,单独维护(封装),此时记者类不但与具体报社类解耦,甚至与报社抽象类解耦:
public abstract class Repoter {
protected String msg;
protected Relation relation;
public abstract void getNewNews(String msg);
}
public class SpecificRepoter extends Repoter {
public SpecificRepoter(Relation relation){
this.relation = relation;
}
public void getNewNews(String msg){
this.msg = msg;
relation.notifyNewspaperOffice(msg);
}
}
public interface Relation {
public void registerNewspaperOffice(NewspaperOffice no);
public void removeNewspaperOffice(NewspaperOffice no);
public void notifyNewspaperOffice(String msg);
}
public class SpecificRelation implements Relation {
private List<NewspaperOffice> relation;
public SpecificRelation(){
relation = new ArrayList<NewspaperOffice>();
}
public void registerNewspaperOffice(NewspaperOffice no) {
if(!relation.contains(no)){
relation.add(no);
}
}
public void removeNewspaperOffice(NewspaperOffice no) {
if(relation.contains(no)){
relation.remove(no);
}
}
public void notifyNewspaperOffice(String msg) {
if(null != relation && relation.size()>0){
for(NewspaperOffice no : relation){
no.update(msg);
}
}
}
}
public abstract class NewspaperOffice {
protected Relation relation;
protected String newMsg;
public void register(){
relation.registerNewspaperOffice(this);
}
public void remove(){
relation.removeNewspaperOffice(this);
}
public abstract void update(String newMsg);
}
public class PeopleDaily extends NewspaperOffice{
public PeopleDaily(Relation relation){
this.relation = relation;
}
public void update(String newMsg) {
this.newMsg = newMsg;
System.out.println("People Daily got "+newMsg);
}
}
浙公网安备 33010602011771号