控制流反转

引言

控制流反转1指将通常的控制流从调用者代码反转到被调用者代码,以便更好的分离关注点和松耦合。观察者模式是这一准则的主要实现形式之一。
文章为了更好的讲解,下面介绍一个设计场景。允许用户以不同的格式选择和显示数字的小程序,即幸运数小程序

动机

大量有状态的对象需要保持一致。例如幸运数小程序,其支持用户选取一个1~10的幸运数,用户可以用不同的方法选取幸运数,如输入数字的数码、输入数字的名称和用滑动条选取数字。
要求1:每个方法的修改要体现在其他方法上
要求2:能扩展其他的方法,如输入罗马数字和输入二进制数字
新手一般会使用两两依赖的方式,如类图所示,此设计至少有两条制约。
制约1:紧耦合
制约2:低可扩展性,增删一个方法会修改其他所有方法
n个方法的同步复杂度是n*(n-1)

IntergerPanel
SliderPanel
TextPanel

MVC分解

避免两两依赖而实现数据同步的方法是将抽象分离为保存数据显示数据修改数据。MVC的解决方案模板不计其数,例如视图和控制器可以融为一体。MVC的不明确性使它在软件设计中不易掌握,而有一种更为具体的思想——观察者模式。

观察者模式

«interface»
Observer
Model
int aNumber
void addObserver(Observer)
void removeObserver(Observer)
int getNumber()
void setNumber()
IntegerPanel
SliderPanel
TextPanel

模型和观察者间的控制流

观察者不是通过调用模型的方法来了解模型的信息,而是等待模型反向调用它们,这种想法称为“好莱坞原则”。观察者上定义的方法称为“回调”。

public interface Observer{
	void newNumber(int pNumber); //模型有个新的值,是这个数
}
public class Model{
	private int aNumber = 5;
	private ArrayList<Observer> aObservers = new ArrayList<>();
	public void addObserver(Observer pObserver){
		aObservers.add(pObserver);
	}
	public void removeObserver(Observer pObserver){
		aObservers.remove(pObserver);
	}	
	private void notifyObservers(){
		for(Observer observer:aObservers){
			observer.newNumber(aNumber);
		}
	}
	public void setNumber(int pNumber){
		if(pNumber<=0){aNumber=1;}
		else if(pNumber>10){aNumber=10;}
		else{aNumber=pNumber;}
		notifyObservers();
	}
}

模型和观察者间的数据流

策略1:通过回调方法的参数来提供,称为推(push)数据流策略,模型将数据推给观察者
策略2:观察者拉取模型上的信息,称为拉(pull)数据流策略

事件驱动

另一种看待回调方法的思路是将其看作事件,模型是事件源,观察者是事件处理程序。


  1. 参考Martin P.Robillard《Introduction to Software Design with Java》 ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值