案例分析:设计模式与代码的结构特性
Posted wanglan1996
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了案例分析:设计模式与代码的结构特性相关的知识,希望对你有一定的参考价值。
1.观察者设计模式:
1.1 动机:建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。
1.2 模式定义:建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应做出反应。在此,发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间没有相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展,这就是观察者模式的模式动机。
1.3 分析:观察者模式描述了如何建立对象与对象之间的依赖关系,如何构造满足这种需求的系统。这一模式中的关键对象是观察目标和观察者,一个目标可以有任意数目的与之相依赖的观察者,一旦目标的状态发生改变,所有的观察者都将得到通知。作为对这个通知的响应,每个观察者都将即时更新自己的状态,以与目标状态同步,这种交互也称为发布-订阅(publishsubscribe)。目标是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅它并接收通知。
1.4 优点:观察者模式可以实现表示层和数据逻辑层的分离,并定义了稳定的消息更新传递机制,抽象了更新接口,使得可以有各种各样不同的表示层作为具体观察者角色。观察者模式在观察目标和观察者之间建立一个抽象的耦合。观察者模式支持广播通信。观察者模式符合“开闭原则”的要求。
1.5 缺点:如果一个观察目标对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间。如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃。观察者模式没有相应的机制让观察者知道所观察的目标对象是怎么发生变化的,而仅仅只是知道观察目标发生了变化。
2.基于随机路由的通信仿真2.1 事件源是被观察
2.1 被观察者:转发端口
2.2 事件:随机生成的端口号
2.3 观察者是转发协议和数据包
2.4 系统要随时通知转发的数据包可以进行转发的数据报文。
3 关键代码:
3.1 定义数据包节点:作为观察者
packet MyMsg{ int source; int destination; int next; int hopCount = 0; }
3.2 定义路由节点:生成端口并进行通知
simple NodeR { parameters: @signal[arrival](type="long"); @statistic[hopCount](title="hop count"; source="arrival"; record=vector,stats; interpolationmode=none); @display("i=block/routing"); gates: inout gate[]; } network routing_random { types: channel Channel extends ned.DelayChannel { delay = 100ms; } submodules: noder[6]: NodeR; connections: noder[0].gate++ <--> Channel <--> noder[2].gate++; noder[2].gate++ <--> Channel <--> noder[1].gate++; noder[2].gate++ <--> Channel <--> noder[3].gate++; noder[4].gate++ <--> Channel <--> noder[3].gate++; noder[3].gate++ <--> Channel <--> noder[5].gate++; }
3.2 定义转发协议:具体定义观察和转发的方法
#include <stdio.h> #include <string.h> #include <omnetpp.h> #include "MyMsg_m.h" using namespace omnetpp; class NodeR : public cSimpleModule { private: simsignal_t arrivalSignal; protected: virtual MyMsg *generateMessage(); virtual void forwardMessage(MyMsg *msg); virtual void initialize() override; virtual void handleMessage(cMessage *msg) override; }; Define_Module(NodeR); void NodeR::initialize() { arrivalSignal = registerSignal("arrival"); if(getIndex() == 0) { MyMsg *msg = generateMessage(); scheduleAt(0.0 , msg); } } void NodeR::handleMessage(cMessage *msg) { MyMsg *ttmsg = check_and_cast<MyMsg *>(msg); if(ttmsg->getDestination() == getIndex()) { int hopcount = ttmsg->getHopCount(); emit(arrivalSignal , hopcount); EV << "Message " << ttmsg << " arrived after " << hopcount << " hops. "; bubble("ARRIVED, starting new one!"); delete ttmsg; EV << "Generating another message: "; MyMsg *newmsg = generateMessage(); EV << newmsg << endl; forwardMessage(newmsg); } else { forwardMessage(ttmsg); } } MyMsg *NodeR::generateMessage() { int src = getIndex(); int n = getVectorSize(); int dest = intuniform(0 , n-2); if(dest >= src) dest++; char msgname[20]; sprintf(msgname,"src-%d-dst-%d",src,dest); MyMsg *msg = new MyMsg(msgname); msg->setSource(src); msg->setDestination(dest); return msg; } void NodeR::forwardMessage(MyMsg *msg) { msg->setHopCount(msg->getHopCount()+1); int n = gateSize("gate"); int k = intuniform(0 , n-1); EV << "Forwarding message " << msg << " on gate[" << k << "] "; send(msg,"gate$o",k); }
观察者在这个模式的实验性:在这个场景下,一个路由节点对应多个转发端口,转发端口的开闭状态会影响报文转发路径,比较适合这一模式。:观察者设计模式降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。使代码结构更清晰。
以上是关于案例分析:设计模式与代码的结构特性的主要内容,如果未能解决你的问题,请参考以下文章