提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
观察者模式+组合模式模拟公司加班通知
一、问题描述
某个公司的某个部门需要集体加班,该部门的所有员工都将收到加班通知;如果是某个员工需要加班,则只有该员工收到通到加班通知。使用设计模式模拟实现加班通知功能。
二、问题分析
1.分析思路:
本题分析可以得出需要使用观察者模式,但是又不能完全符合题干要求,继续分析得出员工和部门之间是整体与部分的关系,所以可以用组合模式来解决实例中描述的通知部门加班和通知个人加班的问题。
2.类图:
三、观察者模式简介
观察者模式(Observer Pattern):定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象都得到通知并被自动更新。
1.观察者模式的优点
(1)可以实现表示层和数据逻辑层的分离,定义了稳定的消息更新传递机制,并抽象了更新接口,使得可以有各种各样不同的表示层充当具体观察者角色。
(2)在观察目标和观察者之间建立一个抽象的耦合。观察目标只需要维持一个抽象观察者的集合,无须了解其具体观察者,由于观察目标和观察者没有紧密地耦合在一起,因此它们可以属于不同的抽象化层次。
(3)支播通信,观察目标会向所有已注册的观察者对象发送通知,简化了一对多系统设计的难度
(4)符合开闭原则,增加新的具体观察者无须修改原有系统代码,在具体观察者与观察目标之间不存在关联关系的情况下增加新的观察目标也很方便。
2.观察者模式的缺点
(1)如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。
(2)如果在被观察者之间有循环依赖的话, 被观察者会触发它们之间进行循环调用,导致系统崩溃。在使用观察考模式时要特别注意这一点。
(3)如果对观察者的通知是通过另外的线程进 行异步投递的话,系统必须保证投递是以自恰的方式进行的。
(4)虽然观察者模式可以随时使观察者知道所观察的对象发生了变化,但是观察者 模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的。
3.应用场景
(1)一个抽象模型有两个方面,其中一个方面依赖于另一个方面,将这两个方面封装在独立的对象中使它们可以各自独立地改变和复用。
(2)一个对象的改变将导致一个或多个其他对象也发生改变,而并不知道具体有多少对象将发生改变,也不知道这些对象是谁。
(3)需要在系统中创建一个触发链,A对象的行为将影响B对象,B对象的行为将影响C对象,可以使用观察者模式创建一种链式触发机制。
(4)比较经典的引用,例如MVC模式。
四、代码及结果
目录结构为:
目标类——AbstractNotify接口:
public abstract class AbstractNotify {
public AbstractObserver Observers;
abstract public void SetObserver(AbstractObserver Observer);
abstract public void PublishNotify();
}
具体目标类——ConcreteNotify:
public class ConcreteNotify extends AbstractNotify{
@Override
public void SetObserver(AbstractObserver Observer) {
this.Observers=Observer;
}
@Override
public void PublishNotify() {
Observers.Notify();
}
}
观察者接口类(同时是抽象构件)——AbstractObserver:
public interface AbstractObserver {
public void Notify();
}
}
具体观察者类(同时充当叶子)——EmployeeObserver:
public class EmployeeObserver implements AbstractObserver{
String Name;
EmployeeObserver(String name)
{
this.Name=name;
}
@Override
public void Notify() {
System.out.println("员工:"+Name+"收到加班通知");
}
}
具体观察者类CompanyObserver(同时充当容器):
import java.util.ArrayList;
import java.util.List;
public class CompanyObserver implements AbstractObserver{
private ArrayList<AbstractObserver> abstractObservers = new ArrayList<AbstractObserver>();
private String Name;
CompanyObserver(String name)
{
this.Name=name;
}
public void AddAbstractObservers(AbstractObserver abstractObserver) {
abstractObservers.add(abstractObserver);
}
public void RemoveAbstractObservers(AbstractObserver abstractObserver) {
abstractObservers.remove(abstractObserver);
}
@Override
public void Notify() {
System.out.println("部门:"+Name+"收到公司加班通知,现在通知所有人");
if (abstractObservers != null) {
for (AbstractObserver a1 : abstractObservers
) {
a1.Notify();
}
}
}
}
Client类:
public class Clint {
public static void main(String[] args) {
ConcreteNotify concreteNotify = new ConcreteNotify();
CompanyObserver company = new CompanyObserver("水木集团");
AbstractObserver employee1 = new EmployeeObserver("小施");
AbstractObserver employee2 = new EmployeeObserver("小代");
AbstractObserver employee3 = new EmployeeObserver("小张");
AbstractObserver employee4 = new EmployeeObserver("小孙");
AbstractObserver employee5 = new EmployeeObserver("小陆");
System.out.println("------------------全体通知----------------------");
company.AddAbstractObservers(employee1);
company.AddAbstractObservers(employee2);
company.AddAbstractObservers(employee3);
company.AddAbstractObservers(employee4);
company.AddAbstractObservers(employee5);
concreteNotify.SetObserver(company);
concreteNotify.PublishNotify();
System.out.println("------------------单独通知----------------------");
concreteNotify.SetObserver(employee1);
concreteNotify.PublishNotify();
concreteNotify.SetObserver(employee2);
concreteNotify.PublishNotify();
}
}
运行结果: