首页 > 其他分享 >观察者模式

观察者模式

时间:2024-10-15 16:12:11浏览次数:2  
标签:proccess void 观察者 模式 ProccessBar pathName public FileSplitter

前言

这个东西写用的少,框架中用的多。有一次面试中,遇到了,平时我没有用过,现在整理一下。

观察者模式解决的问题是什么?

有这样的一种场景,比如说一个对象的状态发生改变,所有的依赖对象将会得到通知。

模型如下:

就是这样一个境地,那么问题来了,这样耦合性就大,比如说我要添加一个观察者,那么改动的对象就是被监听对象。

也就是说监听对象不稳定,这里问题就非常大,一般看到这个时候呢,其实100%需要重构。因为连接线最多的地方基本上要是稳定的。

观察者模式就是来降低耦合。

正文

手写代码,没有经过验证,只是介绍思想。

上面的例子是文件切割,然后进度条反馈进度。

public class FileSplitter
{
   string pathName;
   
   ProccessBar processbar;
   Public FileSplitter(string pathName)
   {
      this.pathName=pathname;
   }
   public void splitter()
   {
      //处理事务....
      processbar.setvalue(xx);
   }
}

这里有个问题,那就是ProccessBar processbar;是面向具体实现类。

这里考虑是否进度条的种类会发生变化?可能有不同的进度条。

那么可以把进度条传递进来:

public class FileSplitter
{
   string pathName;
   
   ProccessBar processbar;
   Public FileSplitter(string pathName,ProccessBar processbar)
   {
      this.pathName=pathname;
      this.processbar=processbar;
   }
   public void splitter()
   {
      //处理事务....
      processbar.setvalue(xx);
   }
}

FileSplitter 依赖于ProccessBar 的具体实现,这个时候就有个问题,因为ProccessBar 是winform的组件,这样无法复用。

还有一个问题,那就是进度条和FileSplitter耦合了,耦合是可以的,但是这两者并不相关,他们不应该存在耦合。

是啊,文件分割和进度条他们之间没有关系啊。

这个时候可能提出那么把ProccessBar去面向接口吧,不面向具体实现类。这个时候是不完全对的,面向接口抽象是为了延迟实现,但是这两者本身就不应该耦合。

那么这个时候就开始分析ProccessBar processbar;到底是做什么的?

ProccessBar 是进度条,进度条是什么?进度条是展现给人们看的进度。

这个时候抓住一个关键点在于,对于FileSplitter来说需要的只是一个进度通知,而不是一个进度条。

interface Iprogress{
  void showProgress(float value);
}

public class FileSplitter
{
   string pathName;
   
   Iprogress process;
   Public FileSplitter(string pathName)
   {
      this.pathName=pathname;
   }
   public void splitter()
   {
      //处理事务....
      if(process!=null)
      {
         process.showProgress(...);
      }
   }
}

 

这个时候就很好了,这个时候就是带通知的文件系统,是一个整体。

这个时候还有一个问题,那就是既然是进度通知,那么通知的对象就不仅仅是一个,还有一个问题就是process如何传进来,那么可以改一下。

interface Iprogress{
  void showProgress(float value);
}

public class FileSplitter
{
   string pathName;
   List<Iprogress> processes;
   Public FileSplitter(string pathName,ProccessBar process=null)
   {
      this.pathName=pathname;
      this.processes=new List<IProgress>;
   }
   public void addProcess(Iproccess proccess)
   {
      processes.add(proccess);
   }
   public void RemoveProcess(Iproccess proccess)
   {
      processes.remove(proccess);
   }
   public void splitter()
   {
      //处理事务....
      foreach(var proccess in processes)
      {
         process.showProgress(...);
      }
   }
}

 

那么要使用ProccessBar,这样写:

class mysql:form,Iprogress
{
   ProccessBar proccessbar;
   void dosomething()
   {
       FileSplitter f=new FileSplitter ();
       f.addProcess(this);
   }
   //具体实现
   void showProgress(float value)
   {
      proccessbar.setValue(value);
   }
}

很多人看到观察者想到了委托,很大一部门原因是List processes;,可以替换成委托。

上面的代码还有一个问题就是:

public void splitter()
   {
      //处理事务....
      foreach(var proccess in processes)
      {
         process.showProgress(...);
      }
   }

违法了单一原则。

因为切割对象又做了通知,那么可以这样。

public void splitter()
{
   //处理事务....
   noticeProcesses();
}
protect void noticeProcesses()
{
    foreach(var proccess in processes)
      {
         process.showProgress(...);
      }
}

那么这里还有一个问题,就是进度通知很多类都需要,那么如何把:

public void addProcess(Iproccess proccess)
{
   processes.add(proccess);
}
public void RemoveProcess(Iproccess proccess)
{
   processes.remove(proccess);
}
protect void noticeProcesses()
{
    foreach(var proccess in processes)
    {
       process.showProgress(...);
    }
}

这一部分移出去?很多人考虑到把进度封装成一个类,然后让具体实现类继承就可以。

观察者模式的好处:

1.无需指定观察者,通知会自动传播。

2.观察者自己实现订阅机制,而目标对象自己不知道。调用noticeProcesses即可。

还有这种实现方式,https://www.runoob.com/design-pattern/observer-pattern.html

标签:proccess,void,观察者,模式,ProccessBar,pathName,public,FileSplitter
From: https://www.cnblogs.com/Peretsoft/p/18467748

相关文章

  • 在K8S中,所支持的存储供应模式有哪些?
    在Kubernetes(K8S)中,存储供应(StorageClass)是用于描述如何配置存储卷(PersistentVolumes)的一种抽象。它允许用户请求具有特定特性的存储而不需要指定具体的存储后端。以下是Kubernetes中所支持的一些存储供应模式:动态配置(DynamicProvisioning):动态配置允许用户基于存储类来请......
  • 老虎老鼠分不清楚-《分析模式》漫谈38
    DDD领域驱动设计批评文集做强化自测题获得“软件方法建模师”称号《软件方法》各章合集“AnalysisPatterns”的第3章有这么一句:Wealsoneedtorecordtheclinicalknowledgeofthe link betweenweightlossanddiabetes.UsingthemodelshowninFigure3.7,w......
  • 尚硅谷rabbitmq2024 工作模式路由篇 第11节 答疑
    StringexchangeName="test_direct";/!创建交换机人图全channel.exchangeDeclare(exchangeName,BuiltinExchangeType.DIREcT,b:true,b1:false,b2:false,map:null);/1创建队列Stringqueue1Name="test_direct_queue1";Stringqueue2Name="test......
  • 01.单例模式设计思想
    01.单例模式设计思想目录介绍01.单例模式基础介绍1.1模式的动机1.2单例模式特点1.3单例模式定义1.4单例使用场景1.5单例模式思考02.单例模式设计思考2.1为何要用单例2.2处理资源访问冲突2.3表示全局唯一类03.如何实现单例模式3.1如何实现一个单例3......
  • RabbitMQ的五种消息模式
    一、简单模式(Simple)最基础的模式,适用于简单的场景,生产者直接向队列发送消息,消费者从监听的队列中获取消息,没有交换机二、工作队列模式(WorkQueues)实现负载均衡,平摊压力,多个消费者监听同一个队列,队列将消息均匀分配给消费者,同样没有交换机三、发布/订阅模式(Publish/Subscribe)......
  • 设计模式--Java面试题
    目录什么是设计模式?你是如何理解设计模式的?设计模式的理解:设计模式的分类:如何使用设计模式:面对一个具体问题,你如何决定使用哪种设计模式?一些常见的问题和对应的设计模式:我想了解在实际项目中如何应用设计模式,有没有具体的案例可以分享?解释创建型、结构型和行为型设计模式的区......
  • 设计模式
    什么是设计模式点击查看代码设计模式是一套被反复使用,多数人知晓,经过分类编目,代码设计经验的总结。2.设计模式的七大原则点击查看代码*开闭原则:对扩展开发,对修改封闭*单一职责原则:一个类只负责一个功能领域的相应职责*里氏转换原则:所有引用基类的地方必须能透明......
  • RabbitMQ的五种模式
    一、五种模式详解1.简单模式(Queue模式)当生产端发送消息到交换机,交换机根据消息属性发送到队列,消费者监听绑定队列实现消息的接收和消费逻辑编写.简单模式下,强调的一个队列queue只被一个消费者监听消费.1.1结构生产者:生成消息,发送到交换机交换机:根据消息属性,将消息......
  • 从SQL Server过渡到PostgreSQL:理解模式的差异
    从SQLServer过渡到PostgreSQL:理解模式的差异 从SQLServer过渡到PostgreSQL:理解模式的差异前言随着越来越多的企业转向开源技术,商业数据库管理员和开发者也逐渐面临向PostgreSQL迁移的需求。虽然SQLServer和PostgreSQL共享许多数据库管理系统(RDBMS)的基本概念,但它们在处......
  • gaussdb 基础管理 数据库 表 用户 模式 权限 存储过程
    数据库database#创建数据库,指定字符集UTF8,缺省情况下新数据库将通过复制标准系统数据库template0来创建,且仅支持使用template0来创建。CREATEDATABASEdevdbENCODING'UTF8'template=template0;CREATEDATABASEtestdb;标识符的命名需要遵守如下规范:*标识符需要为......