花两个小时彻底搞懂设计模式之观察者模式,值

本文通过比喻解释了软件框架与应用程序的关系,并介绍了观察者模式在应对客户需求变化中的重要作用。以建筑行业为参照,说明了框架如何在软件开发中提供灵活性,允许在不改变主体结构的情况下进行定制化修改。文中通过代码示例展示了观察者模式在文件分割程序中的应用,强调了其在人机交互程序中更新界面和通知机制的关键角色。
摘要由CSDN通过智能技术生成

简介

  学习观察者模式前先了解一个概念,框架。目前各种框架层出不穷(MFC、spring等),那框架和应用之间的关系又是什么?这里的应用就是指我们开发的各种程序(office、qq…)。

  举个恰当的例子,大约1970年之前吧,程序开发是结构化的。什么是结构化的?就是一个功能一个函数,小拜负责A函数、小特负责B函数、小奥负责C函数。每个函数有具体的功能,这在开发软件之前已经商定好了。这种方法就类似于修房子,小拜干砖瓦活,小特搞装修、小奥通水电。那些年,软件需求量不大,用户要求也少,毕竟刚学会走(提不出啥要求,开发个软件,让我咋用我就咋用),大家各司其职,也美滴狠!

  时间到了1990年,用户接受了软件这个好东西,有了自己的想法了(这就危险了,毕竟想法越多越...)。软件前辈们发现,之前的结构化模式不太美了,客户隔三差五变需求,提要求。改装修就会影响到水电,甚至砖瓦活也得重折腾,小拜、小特、小奥就很辛苦!

  于是,新的东西诞生了!没错,就是框架!鲁迅先生说过:“人的性情总是喜欢调和、折中的。礕如你说这屋子太暗,须在这里开一个窗,大家一定不允许的。但如果你主张拆掉屋顶,他们就会来调和,愿意开窗了。”到了给软件提要求时可不是这样了,拆屋顶都是小需求,动辄要拿千斤顶把房子举高高呢!

  太阳底下没有新鲜事。小许,一位从建筑工人转行到程序员的前辈崭露头角,估计是九几年房地产不景气,也或许是大家不买期房的账了,这都不是重点。重点是,他发现之前搞房地产都是先钢筋混凝土先搞框架,再是水电,最后装修。怎么新兴的软件行业,精装修完了,客户让把承重墙换个位置?

  一天晚上,大约两三点钟,小许想起了之前之前在币贵园当董事的杨总。记得之前他们的墙体容易开裂,“框架‘’容易出问题,问问他或许能有点启发!

  “出卖我的爱,背着我离开,知道真相的我眼泪流下来…”一段火辣的手机铃声后,电话通了。这个点杨总没睡觉,不是加班哦,是人在巴黎爬埃菲尔铁塔呢。寒暄过后,小许抛出了困惑:“你们房子的框架出了问题,或者是客户让你们改框架,你们是如何处理的呢?”。小杨顿了一下,问道:“你是给你自己问,还是给买了我们房子的人问?”。小许思索片刻答道:“给我自己问!”。

  “主要处理办法有两步,首先,客户发现主体有问题,我们会想办法在装修上盖过去!实在不行的话,我们墙体也做的不厚啊,修修补补糊弄过去也就行了,这是负责的做法。实在不想管就直接不搭理这些业主就行了。”,小杨边笑边回答道,“阿印,你怎么老实的跟个百姓似的,哈哈哈”。

  杨总也是艺高人胆大,但是这给许前辈带来了灵感!当下较火的软件当属人机交互程序,也就是有UI界面的。这类程序无非是些按钮、输入框、下拉框、界面显示…,如果能有个类似结构框架的东西,把软件主体搭建起来,甚至水电也预留管道通好。每次给具体客户做的时候就只需要搞搞装修了。当然了,这个软件的框架也要和杨总的币贵园一样,要做的“够薄”,要有足够的适应性来应对客户的更改需求!

  于是乎,框架的概念呼之欲出。各类框架层出不穷,但是万变不离其宗。其核心都逃不开我们今天的主角:观察者模式!

正文

先上类图

在这里插入图片描述

再来代码

//MainForm.cpp
#include <iostream>
#include <string>
#include "IProgress.h"
#include "ProgressBar.h"
#include "MainForm.h"
#include "ConsoleNotifier.h"
#include "FileSplitter.h"
using namespace std;

// class MainForm 主窗体程序
	//按钮点击后  
	//创建了一个控制台通知器
	//创建了一个文件分割器
	//addIProgress 方法完成订阅通知,通知按钮,通知控制台通知器
	//也就是 分割器的进度 既要告知按钮,也要告知界面显示部分
void MainForm::Button1_Click() {

	string filePath = "C:\\Observer_Pattern_Note.txt";
	int number = 100;

	ConsoleNotifier cn;

	FileSplitter splitter(filePath, number);

	//注意 添加订阅的方法 是由发出通知的类所实现的 。
	splitter.addIProgress(this); //		  MainForm 订阅通知
	splitter.addIProgress(&cn); // ConsoleNotifier 订阅通知

	splitter.split();//分割器启动

	splitter.removeIProgress(this);//取消订阅

}

void MainForm::DoProgress(float value)
{
	progressBar->SetValue(value);
}

MainForm::MainForm()
{
	progressBar = new ProgressBar();
}

MainForm::~MainForm()
{
	if (progressBar != NULL)
	{
		delete progressBar;
	}
}

//ProcessBar.cpp
#include "ProgressBar.h"
#include <iostream>
#include <string>
#include "publicFun.h"
ProgressBar::ProgressBar():m_fValue(0)
{
	//构造函数
}

void ProgressBar::SetValue(float fVal)
{
	m_fValue = fVal;

	ConsoleSetCursorPos(1, 0);

	std::cout << "1号订阅者(观察者)汇报:当前进度:";

	for (size_t i = 0; i < m_fValue*20; i++)
	{
		 std::cout << "█";
	}
}
//FileSplitter.cpp
#include "FileSplitter.h"
#include <Windows.h>

void FileSplitter::addIProgress(IProgress* iprogress)
{
	m_iprogressList.push_back(iprogress);
}

void FileSplitter::removeIProgress(IProgress* iprogress) {
	m_iprogressList.remove(iprogress);
}

void FileSplitter::split()
{
	//1.读取大文件
	Sleep(500);
	//2.分批次向小文件中写入
	for (int i = 0; i < m_fileNumber; i++) {
		//...

		float progressValue = m_fileNumber;
		progressValue = (i + 1) / progressValue;
		onProgress(progressValue);//发送通知
	}
}

void FileSplitter::onProgress(float value)
{
	list<IProgress*>::iterator itor = m_iprogressList.begin();

	while (itor != m_iprogressList.end())
	{
		(*itor)->DoProgress(value); //更新进度条
		itor++;
	}
}
//Console.cpp
#include "ConsoleNotifier.h"
#include "publicFun.h"
void ConsoleNotifier::DoProgress(float value)
{
	ConsoleSetCursorPos(2+1, 0);//在第几行 输出信息

	std::cout << "2号订阅者(观察者)汇报:当前进度" << value;
}


int main()
{
	MainForm mf;
	mf.Button1_Click();
	cout << "end...\n";
}

最后上效果图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值