好久没搞java了,要找工作了,复习下设计模式~~
观察者模式:描述的是一对多的关系,当”一”的状态发生变化时,会通知”多”的一端,前提是”多”个对象必须事先注册到”一”的对象上,让“一”知道它们的存在。
举个形象的例子:我们平时订阅杂志,每个订阅者(即观察者)必须到杂志社注册个人信息,杂志社为了在日后能够顺利分发杂志,此时必须保存每个订阅者的信息,当杂志社出版新杂志,它就会通过之前那个记录列表一个一个的分别通知它的每一位订阅者,只要你在它那里注册过,就会一直收到新的杂志。当然,你可以选择取消订阅,这样杂志社就不会再向你送新杂志了。只有杂志社一直存在,就会不停的有人订阅杂志或取消订阅,而这个动作是在整个运行机制中动态发生的。
为了松耦合,我们针对接口编程,这是一个主题的接口,声明三个方法,作用分别是注册订阅者、取消订阅、状态变化时通知所有订阅者
public interface Subject {
public void registerSub(Subscriber sub);
public void cancelSub(Subscriber sub);
public void notifySubs();
}
接下来是主题接口的实现类,ConcreteSubject.java
public class ConcreteSubject implements Subject {
private List<Subscriber> subs = new ArrayList<Subscriber>();
private String state1;
private String state2;
public void registerSub(Subscriber sub) {
subs.add(sub);
}
public void cancelSub(Subscriber sub) {
int index = subs.indexOf(sub);
if (index >= 0) {
subs.remove(sub);
}
}
public void notifySubs() {
for (Subscriber sub : subs) {
sub.update(state1, state2);
}
}
public void stateChanded(String state1, String state2){
this.state1 = state1;
this.state2 = state2;
notifySubs();
}
}
分析这个类:首先,因为当有新消息时会通知所有的订阅者,显然ConcreteSubject的实例必须知道有哪些对象注册到它上面来了,所以ConcreteSubject类中必须有一个集合类型变量:List subs; 用来保存每一个订阅者的引用。由于订阅者可以不同的类型,想要将不同类的对象保存到同一个集合中,最简单的办法就是让不同的订阅者类现实一个共同的接口,我们称之为Subscriber(订阅者),这样前面的集合变量类型就可以通过泛型指明了,即List<Subscriber> subs; 其次,分别实现Subject接口声明的三个方法;最后,我们模拟两个变量state1, state2,当它们发生变化时,会调用notifySubs()更新所有它的注册者。
通过上面的分析,我们需要一个Subscriber接口:
public interface Subscriber {
public void update(String state1, String state2);
}
假设有三个订阅者
小明:
public class XiaoMing implements Subscriber {
private Subject subject;
private String state1;
private String state2;
public XiaoMing(Subject subject) {
this.subject = subject;
subject.registerSub(this);
}
public void update(String state1, String state2) {
this.state1 = state1;
this.state2 = state2;
System.out.println("XiaoMing被通知了...");
}
}
后两个类与小明类大同小异
大明:
public class DaMing implements Subscriber {
private Subject subject;
private String state1;
private String state2;
public DaMing(Subject subject) {
this.subject = subject;
subject.registerSub(this);
}
public void update(String state1, String state2) {
this.state1 = state1;
this.state2 = state2;
System.out.println("DaMing被通知了...");
}
}
小红:
public class XiaoHong implements Subscriber {
private Subject subject;
private String state1;
private String state2;
public XiaoHong(Subject subject) {
this.subject = subject;
subject.registerSub(this);
}
public void update(String state1, String state2) {
this.state1 = state1;
this.state2 = state2;
System.out.println("XiaoHong被通知了...");
}
这三个实际的订阅者 实现了一个共同的接口,类似于一个标识,告诉主题“我是一个订阅者”,当注册后,如果有新消息请通知我。我们看到,Subscriber接口中只声明了一个方法update(),这个接口的作用在于为“主题”通知”订阅者”提供一个统一的方法。
测试:
public class Main {
public static void main(String[] args) {
//注册
ConcreteSubject subject = new ConcreteSubject();
XiaoMing xm = new XiaoMing(subject);
DaMing dm = new DaMing(subject);
XiaoHong xh = new XiaoHong(subject);
//Subject状态发生变化
subject.stateChanded("new1", "new2");
System.out.println();
subject.cancelSub(dm);
subject.stateChanded("new3", "new4");
}
}
可以看到,订阅者注册到主题之后,主题的状态发生变化(对象中变量被重设)时,会依次通知每个订阅者,而当订阅者取消订阅后,主题的新消息再不再通知它。
总结:
观察者模式的关键在于:一个订阅接口,多个订阅者实现类,主题中以一个集合的形式保存所以订阅者,这样就可以向每个订阅者发送消息
观察者模式的灵活性在于:如果有增加一个订阅者,完全不用修改ConcreteSubject类,直接让新添加的订阅者实现Subscriber接口,并在构造函数中向主题注册,完了就可以直接用了。
分享到:
相关推荐
文档加代码,如果看完pdf,观察者模式还没学会,感觉你没必要学设计模式了,文档非常通俗易通,适合新手上手。
《白话设计模式》文档很可能是以通俗易懂的方式介绍设计模式的入门读物。 在软件开发过程中,设计模式可以帮助我们更有效地组织代码,提高代码的可读性和可维护性。设计模式通常分为三类:创建型、结构型和行为型...
5. 观察者模式:用于实现事件驱动编程,如在训练过程中监控损失函数的变化,或者在模型状态改变时触发其他操作。 6. 适配器模式:在使用第三方库或接口时,适配器模式可以将不兼容的接口转换为可用的接口,例如将...
例如,工厂模式、单例模式、建造者模式属于创建型,适配器模式、装饰器模式属于结构型,而观察者模式、策略模式属于行为型。理解并熟练应用设计模式可以提高代码的可读性、可维护性和可扩展性。 2. **C++Templates....
5. 设计模式:代码中可能会体现出一些常见的设计模式,如工厂模式、观察者模式等,显示了编程的规范化和灵活性。 6. 数据处理:如果项目涉及数据,那么数据的读取、清洗、分析和展示的代码将揭示团队的数据处理能力...
- 了解常见的设计模式,如工厂模式、单例模式、观察者模式,以解决特定设计问题。 - 应用策略模式来封装算法,使代码更灵活和可扩展。 9. **命名空间**: - 使用命名空间避免全局作用域中的名字冲突。 - 使用`...
3. **设计模式**:如果代码量较大,可能涉及到了面向对象的设计模式,如单例、工厂、观察者等,这些模式有助于代码的组织和复用。 4. **软件工程实践**:良好的代码结构、注释、模块化和面向接口的设计,都是软件...
- **属性**:讨论了存储属性、计算属性、属性观察者等属性相关概念。 - **方法**:介绍了实例方法、类型方法等方法类型。 - **下标脚本**:解释了下标的使用方式及其实现机制。 - **继承**:讲述了继承的概念及其...
对于初学者或正在进行毕业设计、课程设计的同学来说,这是一个很好的实践项目。以下是对该项目涉及的技术点进行的详细说明: 1. **Servlet**:Servlet是Java编程语言中用于扩展服务器功能的接口。在这个项目中,...
- **MVC模式**:观察项目是否遵循Model-View-Controller架构,了解各部分职责。 - **异常处理**:检查代码中如何捕获和处理可能出现的错误和异常。 - **响应式设计**:分析Bootstrap如何帮助实现页面在不同设备上的...
这是中国现代文学史上的第一篇白话小说,标志着现代白话文小说的开端。 12. **绝句的格式**:错误。“绝句”一般为四句,每句五个字或七个字,而不是七言八句的形式。 13. **修辞手法的应用**:正确。“排比”和...
2. 无监督学习:用于发现数据中的模式和结构,如聚类算法(K-means、DBSCAN)、主成分分析(PCA)和关联规则学习(Apriori)等。 3. 半监督学习和强化学习:前者在少量标注数据下进行学习,后者涉及环境交互,通过...
此外,本项目也适用于计算机科学和机器学习的学习者作为毕业设计或课程设计的参考。它不仅锻炼了编程技能,还涵盖了深度学习和神经网络的基础理论,为深入理解和应用这些技术打下坚实基础。 总的来说,"利用霍普...
它通过模拟生物进化过程中的“适者生存”原则,通过迭代过程逐步优化解决方案,寻找问题的全局最优解。在特征选择中,GA可以用于筛选出对目标变量最有影响力的特征子集。 4. **自变量降维**:在数据分析和建模中,...