设计模式—— 六:开闭原则

面向对象六大原则详解 本文来说下面向对象六大原则 文章目录概述 概述 阅读详情

什么是开闭原则?

开闭原则的定义:

Software entities like classes,modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。)

在开发软件的过程中,因为变化 、升级和维护等原因需要对软件原有的代码进行修改,可能会将错误引入原本已经测试过的旧代码中,破坏原有的系统,因此,当软件需求变化时,我们应尽量运用扩展的方式来实现变化,而不是修改原来的代码。

开闭原则详解

以书店销售书籍为例:

6-1:书店售书类图


在这里插入图片描述
 

书籍接口IBook:

复制代码
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">interface</span> <span style="color:#4078f2">IBook</span> {   
     <span style="color:#a0a1a7"><em>//书籍有名称</em></span>
     <span style="color:#a626a4">public</span> String <span style="color:#4078f2">getName</span>();
     <span style="color:#a0a1a7"><em>//书籍有售价</em></span>
     <span style="color:#a626a4">public</span> <span style="color:#986801">int</span> <span style="color:#4078f2">getPrice</span>();
     <span style="color:#a0a1a7"><em>//书籍有作者</em></span>
     <span style="color:#a626a4">public</span> String <span style="color:#4078f2">getAuthor</span>();
}
</code></span></span>

小说类NovelBook:
是一个具体的实现类,是所有小说书籍的总称。

复制代码
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">NovelBook</span> <span style="color:#a626a4">implements</span> <span style="color:#4078f2">IBook</span> {
     <span style="color:#a0a1a7"><em>//书籍名称</em></span>
     <span style="color:#a626a4">private</span> String name;       
     <span style="color:#a0a1a7"><em>//书籍的价格</em></span>
     <span style="color:#a626a4">private</span> <span style="color:#986801">int</span> price; 
     <span style="color:#a0a1a7"><em>//书籍的作者</em></span>
     <span style="color:#a626a4">private</span> String author;             
     <span style="color:#a0a1a7"><em>//通过构造函数传递书籍数据</em></span>
     <span style="color:#a626a4">public</span> <span style="color:#4078f2">NovelBook</span>(String _name,<span style="color:#986801">int</span> _price,String _author){
<span style="color:#c18401">this</span>.name = _name;
             <span style="color:#c18401">this</span>.price = _price;
             <span style="color:#c18401">this</span>.author = _author;
     }  
     <span style="color:#a0a1a7"><em>//获得作者是谁</em></span>
     <span style="color:#a626a4">public</span> String <span style="color:#4078f2">getAuthor</span>() {
             <span style="color:#a626a4">return</span> <span style="color:#c18401">this</span>.author;
     }
     <span style="color:#a0a1a7"><em>//书籍叫什么名字</em></span>
     <span style="color:#a626a4">public</span> String <span style="color:#4078f2">getName</span>() {
             <span style="color:#a626a4">return</span> <span style="color:#c18401">this</span>.name;
     }
     <span style="color:#a0a1a7"><em>//获得书籍的价格</em></span>
     <span style="color:#a626a4">public</span> <span style="color:#986801">int</span> <span style="color:#4078f2">getPrice</span>() {
             <span style="color:#a626a4">return</span> <span style="color:#c18401">this</span>.price;
     }
}
</code></span></span>

书店售书类:

复制代码
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">BookStore</span> {
     <span style="color:#a626a4">private</span> <span style="color:#a626a4">final</span> <span style="color:#a626a4">static</span> <span style="color:#986801">ArrayList</span> <span style="color:#986801">bookList</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">ArrayList</span>();
     <span style="color:#a0a1a7"><em>//static静态模块初始化数据,实际项目中一般是由持久层完成</em></span>
     <span style="color:#a626a4">static</span>{
             bookList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">NovelBook</span>(<span style="color:#50a14f">"天龙八部"</span>,<span style="color:#986801">3200</span>,<span style="color:#50a14f">"金庸"</span>));
             bookList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">NovelBook</span>(<span style="color:#50a14f">"巴黎圣母院"</span>,<span style="color:#986801">5600</span>,<span style="color:#50a14f">"雨果"</span>));
             bookList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">NovelBook</span>(<span style="color:#50a14f">"悲惨世界"</span>,<span style="color:#986801">3500</span>,<span style="color:#50a14f">"雨果"</span>));
             bookList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">NovelBook</span>(<span style="color:#50a14f">"金*梅"</span>,<span style="color:#986801">4300</span>,<span style="color:#50a14f">"兰陵笑笑生"</span>));
     }
     <span style="color:#a0a1a7"><em>//模拟书店买书</em></span>
     <span style="color:#a626a4">public</span> <span style="color:#a626a4">static</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">main</span>(String[] args) {
             <span style="color:#986801">NumberFormat</span> <span style="color:#986801">formatter</span> <span style="color:#ab5656">=</span> NumberFormat.getCurrencyInstance();
             formatter.setMaximumFractionDigits(<span style="color:#986801">2</span>);
             System.out.println(<span style="color:#50a14f">"-----------书店卖出去的书籍记录如下:-----------"</span>);
             <span style="color:#a626a4">for</span>(IBook book:bookList){
                     System.out.println(<span style="color:#50a14f">"书籍名称:"</span> + book.getName()+<span style="color:#50a14f">"\t书籍作者:"</span> +book.getAuthor()+<span style="color:#50a14f">"\t书籍价格:"</span>+ formatter.format (book.getPrice()/<span style="color:#986801">100.0</span>)+<span style="color:#50a14f">"元"</span>);
             }
     }
}
</code></span></span>

运行结果:

复制代码
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java">-----------------书店卖出去的书籍记录如下:--------------

书籍名称:天龙八部  书籍作者:金庸    书籍价格:¥<span style="color:#986801">25.60</span>元

书籍名称:巴黎圣母院 书籍作者:雨果    书籍价格:¥<span style="color:#986801">50.40</span>元

书籍名称:悲惨世界  书籍作者:雨果    书籍价格:¥<span style="color:#986801">28.00</span>元

书籍名称:金*梅    书籍作者:兰陵笑笑生 书籍价格:¥<span style="color:#986801">38.70</span>元
</code></span></span>

现在新的需求来了,受移动互联网发展的影响,书店必须打折来维持书店的生存。所有40元以上的书籍9折销售,其他的8折销售。

该如何实现这个变化,有三种方式:

● 修改接口

在IBook上新增加一个方法getOffPrice(),专门用于进行打折处理,所有的实现类实现该方法。但是这样修改的后果就是,实现类NovelBook要修改,BookStore中的main方法也修改,同时IBook作为接口应该是稳定且可靠的,不应该经常发生变化,否则接口作为契约的作用就失去了效能。因此,该方案否定。

● 修改实现类

修改NovelBook类中的方法,直接在getPrice()中实现打折处理。该方法在项目有明确的章程(团队内约束)或优良的架构设计时,是一个非常优秀的方法,但是该方法还是有缺陷的。例如采购书籍人员也是要看价格的,由于该方法已经实现了打折处理价格,因此采购人员看到的也是打折后的价格,会因信息不对称而出现决策失误的情况。因此,该方案也不是一个最优的方案。

● 通过扩展实现变化

增加一个子类OffNovelBook,覆写getPrice方法,高层次的模块(也就是static静态模块区)通过OffNovelBook类产生新的对象,完成业务变化对系统的最小化开发。好办法,修改也少,风险也小,修改后的类图如图6-2所示。

6-2:书店售书类图


在这里插入图片描述

打折销售的小说类OffNovelBook:
仅仅覆写了getPrice方法,通过扩展完成了新增加的业务。

复制代码
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">OffNovelBook</span> <span style="color:#a626a4">extends</span> <span style="color:#4078f2">NovelBook</span> {
     <span style="color:#a626a4">public</span> <span style="color:#4078f2">OffNovelBook</span>(String _name,<span style="color:#986801">int</span> _price,String _author){
             <span style="color:#c18401">super</span>(_name,_price,_author);
     }
     <span style="color:#a0a1a7"><em>//覆写销售价格</em></span>
     <span style="color:#4078f2">@Override</span>
     <span style="color:#a626a4">public</span> <span style="color:#986801">int</span> <span style="color:#4078f2">getPrice</span>(){
             <span style="color:#a0a1a7"><em>//原价</em></span>
             <span style="color:#986801">int</span> <span style="color:#986801">selfPrice</span> <span style="color:#ab5656">=</span> <span style="color:#c18401">super</span>.getPrice();
             <span style="color:#986801">int</span> offPrice=<span style="color:#986801">0</span>;
             <span style="color:#a626a4">if</span>(selfPrice><span style="color:#986801">4000</span>){  <span style="color:#a0a1a7"><em>//原价大于40元,则打9折</em></span>
                     offPrice = selfPrice * <span style="color:#986801">90</span> /<span style="color:#986801">100</span>;
             }<span style="color:#a626a4">else</span>{
                     offPrice = selfPrice * <span style="color:#986801">80</span> /<span style="color:#986801">100</span>;
             }
             <span style="color:#a626a4">return</span> offPrice;
     }
}
</code></span></span>

店打折销售类:
需要依赖子类,稍作修改。

复制代码
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">BookStore</span> {
     <span style="color:#a626a4">private</span> <span style="color:#a626a4">final</span> <span style="color:#a626a4">static</span> <span style="color:#986801">ArrayList</span> <span style="color:#986801">bookList</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">ArrayList</span>();
     <span style="color:#a0a1a7"><em>//static静态模块初始化数据,实际项目中一般是由持久层完成</em></span>
     <span style="color:#a626a4">static</span>{
             bookList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">OffNovelBook</span>(<span style="color:#50a14f">"天龙八部"</span>,<span style="color:#986801">3200</span>,<span style="color:#50a14f">"金庸"</span>));
             bookList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">OffNovelBook</span>(<span style="color:#50a14f">"巴黎圣母院"</span>,<span style="color:#986801">5600</span>,<span style="color:#50a14f">"雨果"</span>));
             bookList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">OffNovelBook</span>(<span style="color:#50a14f">"悲惨世界"</span>,<span style="color:#986801">3500</span>,<span style="color:#50a14f">"雨果"</span>));
             bookList.add(<span style="color:#a626a4">new</span> <span style="color:#4078f2">OffNovelBook</span>(<span style="color:#50a14f">"金*梅"</span>,<span style="color:#986801">4300</span>,<span style="color:#50a14f">"兰陵笑笑生"</span>));
     }  
     <span style="color:#a0a1a7"><em>//模拟书店买书</em></span>
     <span style="color:#a626a4">public</span> <span style="color:#a626a4">static</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">main</span>(String[] args) {
             <span style="color:#986801">NumberFormat</span> <span style="color:#986801">formatter</span> <span style="color:#ab5656">=</span> NumberFormat.getCurrencyInstance();
             formatter.setMaximumFractionDigits(<span style="color:#986801">2</span>);
             System.out.println(<span style="color:#50a14f">"-----------书店卖出去的书籍记录如下:-----------"</span>);
             <span style="color:#a626a4">for</span>(IBook book:bookList){
                      System.out.println(<span style="color:#50a14f">"书籍名称:"</span> + book.getName()+<span style="color:#50a14f">"\t书籍作者:"</span> + book.getAuthor()+ <span style="color:#50a14f">"\t书籍价格:"</span> + formatter.format (book.getPrice()/<span style="color:#986801">100.0</span>)+<span style="color:#50a14f">"元"</span>);
             }
     }
}
</code></span></span>

运行结果:

复制代码
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java">----------------------书店卖出去的书籍记录如下:---------------------

书籍名称:天龙八部  书籍作者:金庸    书籍价格:¥<span style="color:#986801">25.60</span>元

书籍名称:巴黎圣母院 书籍作者:雨果    书籍价格:¥<span style="color:#986801">50.40</span>元

书籍名称:悲惨世界  书籍作者:雨果    书籍价格:¥<span style="color:#986801">28.00</span>元

书籍名称:金*梅   书籍作者:兰陵笑笑生 书籍价格:¥<span style="color:#986801">38.70</span>元
</code></span></span>

开闭原则对扩展开放,对修改关闭,并不意味着不做任何修改,低层模块的变 更,必然要有高层模块进行耦合,否则就是一个孤立无意义的代码片段。

为什么要采用开闭原则?

开闭原则是最基础的一个原则,其余的原则都是开闭原则的具体形态, 也就是说其余五个原则就是指导设计的工具和方法。换一个角度 来理解,依照Java语言的称谓,开闭原则是抽象类,其他五大原则是具体的实现类。

可通过以下几个方面来理解其重要性:
 

1、开闭原则对测试的影响

以上面提到的书店售书为例,IBook接口写完了,实现类NovelBook也写好了,需要写一个测试类进行测试。

小说类的单元测试:

复制代码
<span style="color:#141418"><span style="background-color:#ffffff"><code class="language-java"><span style="color:#a626a4">public</span> <span style="color:#a626a4">class</span> <span style="color:#4078f2">NovelBookTest</span> <span style="color:#a626a4">extends</span> <span style="color:#4078f2">TestCase</span> {
     <span style="color:#a626a4">private</span> <span style="color:#986801">String</span> <span style="color:#986801">name</span> <span style="color:#ab5656">=</span> <span style="color:#50a14f">"平凡的世界"</span>;
     <span style="color:#a626a4">private</span> <span style="color:#986801">int</span> <span style="color:#986801">price</span> <span style="color:#ab5656">=</span> <span style="color:#986801">6000</span>;
     <span style="color:#a626a4">private</span> <span style="color:#986801">String</span> <span style="color:#986801">author</span> <span style="color:#ab5656">=</span> <span style="color:#50a14f">"路遥"</span>;      
     <span style="color:#a626a4">private</span> <span style="color:#986801">IBook</span> <span style="color:#986801">novelBook</span> <span style="color:#ab5656">=</span> <span style="color:#a626a4">new</span> <span style="color:#4078f2">NovelBook</span>(name,price,author);
     <span style="color:#a0a1a7"><em>//测试getPrice方法</em></span>
     <span style="color:#a626a4">public</span> <span style="color:#a626a4">void</span> <span style="color:#4078f2">testGetPrice</span>() {
             <span style="color:#a0a1a7"><em>//原价销售,根据输入和输出的值是否相等进行断言</em></span>
             <span style="color:#c18401">super</span>.assertEquals(<span style="color:#c18401">this</span>.price, <span style="color:#c18401">this</span>.novelBook.getPrice());
     }
}
</code></span></span>

一般一个方法的测试方法一般不少于3种——首先是正常的业务逻辑要保证测试到,其次是边界条件要测试到,然后是异常要测试到,比较重要的方法的测试方法甚至有十多种,而且单元测试是对类的测试,类中的方法耦合是允许的,在这样的条件下,如果再想着通过修改一个方法或多个方法代码来完成变化,是很难做到的。

如果用扩展的方式,新增加的类,新增加的测试方法,只要保证新增加类是正确的就可以了。
 

2、开闭原则可以提高复用性

在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来的,而不是在一个类中独立实现一个业务逻辑。只有这样代码才可以复用,粒度越小,被复用的可能性就越大。那为什么要复用呢?减少代码量,避免相同的逻辑分散在多个角落,避免日后的维护人员为了修改一个微小的缺陷或增加新功能而要在整个项目中到处查找相关的代码。那怎么才能提高复用率呢?缩小逻辑粒度,直到一个逻辑不可再拆分为止。

2、开闭原则可以提高可维护性

一款软件投产后,维护人员的工作不仅仅是对数据进行维护,还可能要对程序进行扩展,维护人员最更意做的事情就是扩展一个类,而不是修改一个类。
 

3、 面向对象开发的要求

万物皆对象,我们需要把所有的事物都抽象成对象,然后针对对象进行操作,但是万物皆运动,有运动就有变化,有变化就要有策略去应对,怎么快速应对呢?这就需要在设计之初考虑到所有可能变化的因素,然后留下接口,等待“可能”转变为“现实”。

如何应用开闭原则?

开闭原则是一个比较抽象的原则,前面5个原则是对开闭原则的具体解释,但是开闭原则并不局限于这么多,它更多地像一句口号,一个目标,而没有提出具体的实现办法。这就需要自己在工作中领会精神,总结办法。

1. 抽象约束

通过接口或抽象类可以约束一组可能变化的行为,并且能够实现对扩展开放,其包含三层含义:第一,通过接口或抽象类约束扩展,对扩展进行边 界限定,不允许出现在接口或抽象类中不存在的public方法;第二,参数类型、引用对象尽 量使用接口或者抽象类,而不是实现类;第三,抽象层尽量保持稳定,一旦确定即不允许修改。

2. 元数据(metadata)控制模块行为

尽量使用元数据来控制程序的行为,减少重复开发。什么是元数据?用来描述环境和数据的数据,通俗地说就是 配置参数,参数可以从文件中获得,也可以从数据库中获得。举个非常简单的例子,login方 法中提供了这样的逻辑:先检查IP地址是否在允许访问的列表中,然后再决定是否需要到数 据库中验证密码(,该行为就是一个 典型的元数据控制模块行为的例子。

3. 制定项目章程

在一个团队中,建立项目章程是非常重要的,因为章程中指定了所有人员都必须遵守的 约定,对项目来说,约定优于配置。

4. 封装变化

对变化的封装包含两层含义:第一,将相同的变化封装到一个接口或抽象类中;第二, 将不同的变化封装到不同的接口或抽象类中,不应该有两个不同的变化出现在同一个接口或 抽象类中。封装变化,也就是受保护的变化(protected variations),找出预计有变化或不稳 定的点,为这些变化点创建稳定的接口,准确地讲是封装可能发生的变化,一旦预测到 或“第六感”发觉有变化,就可以进行封装,23个设计模式都是从各个不同的角度对变化进行 封装的。

【设计模式】为什么说开闭原则 (OCP) 是设计模式的核心追求? 摘要: 开闭原则(OCP)是设计模式的核心目标,强调软件实体应对扩展开放但对修改关闭。通过抽象和多态实现功能扩展,避免直接修改稳定代码,从而提升可维护性和灵活性。其他设计原则实质都是实现OCP原则的具体手段。OCP原则能显著减少回归测试需求,是构建健壮软件架构的基石。 阅读详情

相关推荐

ARM架构下Horizon Client安装全攻略:从依赖检查到环境变量配置

本文详细介绍了在ARM架构设备上安装VMware Horizon Client的全过程,包括依赖检查、软件包获取、系统部署和环境变量配置。特别针对华为鲲鹏等ARM平台,提供了从基础准备到性能优化的完整指南,帮助用户高效完成虚拟桌面客户端的部署与调优。

github5actions的博客 556

六大原则之开闭原则

1. 开闭原则的介绍 开闭原则(Open Closed Principle)是编程中最基础、最重要设计原则 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。 2. 违反开闭原则示例 package com.study; public class Ocp {

小松de博客 2万+

视觉SLAM与激光SLAM简单对比分析

本文旨在梳理目前较为前沿的SLAM技术,包括激光和视觉,主要从精度和实时性两个方面对算法进系评价。对于激光SLAM了解不深,后期需要补充相关算法的核心思想与算法框架。有问题请大佬们随时留言,我再改正。

超爱吃小蛋糕的66的博客 3855

设计模式的六大基本原则(开闭原则、单一职责原则、里氏替换原则、接口隔离原则、依赖倒置原则、迪米特法则)

设计模式的六大基本原则(开闭原则、单一职责原则、历史替换原则、接口隔离原则、依赖倒置原则、迪米特法则)

聂可以的博客 1万+

随机变量序列 收敛 检验 matlab,利用MATLAB验证样条插值的收敛性

问题提出多项式插值是不收敛的,即插值的节点多,效果不一定就好。对样条函数插值又如何呢?理论上证明样条插值的收敛性是比较困难的,但通过本实验可以验证这一理论结果。.实验内容请按一定的规则分别选择等距或者非等距的插值节点,并不断增加插值节点的个数。考虑实验2.1中的函数或选择其他你有兴趣的函数。(中函数)。实验要求(1)随节点个数增加,比较被逼近函数和样条插值函数误差的变化情况。分析所得结果并与拉格朗...

weixin_30895121的博客 4736

uniapp实战:mui-player插件如何完美适配m3u8/flv直播流(附完整代码)

本文详细介绍了如何在Uniapp中使用mui-player插件完美适配m3u8和flv直播流,提供从基础配置到高级优化的全流程解决方案。通过动态加载策略、响应式布局和内存管理,实现跨平台稳定播放,适用于企业级直播应用开发。

weixin_29001655的博客 237

七大原则——开闭原则

开闭原则的定义 开闭原则(Open Closed Principle,OCP)由勃兰特·梅耶(Bertrand Meyer)提出,他在 1988 年的著作《面向对象软件构造》(Object Oriented Software Construction)中提出:软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but c...

m0_37654408的博客 6608

AI Agent在智能腰带中的姿势矫正与提醒

随着人们生活方式的改变,长时间不正确的坐姿、站姿等不良姿势问题日益普遍,这不仅会导致身体疲劳,还可能引发颈椎病、腰椎病等多种健康问题。智能腰带作为一种可穿戴设备,具有实时监测人体姿势的潜力。本研究的目的是将AI Agent引入智能腰带,实现对人体姿势的准确识别、矫正与提醒功能。本研究的范围涵盖了从AI Agent的核心算法原理到智能腰带的实际开发与应用。包括传感器数据的采集与处理、机器学习算法的选择与训练、智能腰带的硬件设计与软件开发,以及在不同场景下的实际应用测试。本文共分为十个部分。

AI 原生应用开发的博客 347

开闭原则 (Open/Closed Principle, OCP)

开闭原则是面向对象设计中的基本原则之一,通过确保软件实体对扩展开放,对修改关闭,可以提高系统的稳定性、灵活性和可维护性。在实际开发中,遵循开闭原则有助于我们设计出高质量的代码,使系统更加健壮和易于扩展。希望这个博客对你有所帮助。如果你有任何问题或需要进一步的例子,请随时告诉我!

qq_42798343的博客 3355

【STM32 CubeMX】I2C中断方式与DMA方式

在STM32 CubeMX环境中,I2C(Inter-Integrated Circuit)通信协议的实现可以采用中断方式或DMA(Direct Memory Access)方式。中断方式通过触发中断来处理数据传输,而DMA方式则利用直接内存访问技术来实现数据传输,减轻了CPU的负担。在选择I2C通信方式时,开发者需要根据具体的应用需求和性能要求来选择合适的方式。STM32 CubeMX提供了图形化配置工具,使得配置I2C通信方式变得更加便捷。

m0_62599305的博客 7749

4.6 鞅-一致可积,L1收敛(Durrett)答案

概率-理论与实例第五章 答案:6 鞅-一致可积,L1收敛

weixin_40614311的博客 1060

设计模式六大原则(六): 开闭原则(Open Closed Principle)

定义: 一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。 问题由来: 在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。 解决方案: 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。 开闭原则是面向对象设计中...

weixin_30861459的博客 152

第14.8章 高翔博士最新开源框架Lightning-LM源码解读(八):位姿平滑器PoseSmoother深度剖析,从原理到代码实现

本文深度解析了高翔博士开源框架Lightning-LM中的位姿平滑器PoseSmoother模块。该模块通过设置平滑因子,在保证位姿准确性的同时减少突变,使位姿变化更平稳。文章详细讲解了模块功能、数据流程和核心代码实现,包括构造函数、拷贝构造函数以及关键的PushDRPose和PushPose函数。重点分析了位姿平滑算法原理,涉及运动有效性校验、位姿队列维护和平滑因子调节等核心机制。此外还介绍了相关C++语法(如显式构造函数、默认拷贝构造)和优化方向。本解析为SLAM学习者提供了位姿平滑处理的实用实现范例。

行知SLAM 607

【专题系列】设计模式—— 六:开闭原则

点击上方“java大数据修炼之道”,选择“设为星标”优质文章, 第一时间送达来源 |https://www.cnblogs.com/three-fighter/p/12353205.h...

hello world! 386

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

设计模式六大设计原则(六):开闭原则

一、定义 Software entities like classes,modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。) ...

chuobenggu7592的博客 164

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

设计模式学习之——六大设计原则之六:开闭原则

定义:Software entities like classes, modules and functions should be open for extension but closed for modifications.     (一个软件实体如类、模块和函数应该对扩展开放,对修改关闭) 直接上例子:     如上IBook定义了数据的三个属性,名称,价格,作者

Mr.傅的专栏 2046

[设计模式之禅读书笔记]006_设计模式六大原则(六):开闭原则

序言 开闭是什么意思呢?显然这是两个词的合体,即开放和闭合的意思。那对什么开放呢?扩展。那有对什么闭合呢?修改。 软件开发最可怕的是什么?是变化。记得以前看过一个笑话,说一个程序员累昏倒了,在医院昏迷了好几天,家人哭的稀里哗啦的,老婆孩子在旁边怎么叫就是不醒。一天他同事来看他,第一句话就是对着躺在病床上的他说:需求又变了。奇迹发生了,那个程序员一下从病床上做起来了。 只是一...

weixin_34049948的博客 140

设计模式六大原则之--开闭原则(OCP)

设计模式六大原则之--开闭原则(OCP)前言描述 前言 The Open - Closed Principle, OCP 软件尸体(类、模块、方法等)应该对扩展开放,但是对修改关闭。 描述 遵循开放-关闭原则设计出来的模块具有两个主要的特征。 “对扩展开放”(Open for extension) 这意味着模块的行为是可以扩展的。 当应用的需求改变是,我们可以对模块扩展,让它可以具备满足那些改变的新行为。换句话说,我们可以改变模块的功能。 “对更改关闭”(Closed for modification) 对

宁静致远的博客 2471

Python:开闭原则(OCP)

在 Python 中,通过 Protocol、ABC、策略模式、工厂模式、装饰器、插件体系等技术,我们可以轻松为系统建立“稳定的抽象层”和“可扩展的实现层”。(Open–Closed Principle,OCP)是 SOLID 原则中最核心的一条,也是整个面向对象设计的精神所在,由 Bertrand Meyer 于 1988 年提出,这意味着:当需求变化或添加新功能时,我们应通过“扩展”来实现,而不是通过“修改”已有、稳定、经过验证的代码。避免“过度抽象”,不要预先为不存在的需求做设计(YAGNI)。

qq_41176800的博客 1086

六大设计模式--OCP(开闭原则):构建可扩展软件的基石

某电商平台促销功能每次迭代都需要修改核心订单类,导致:✅ 双十一活动修改导致支付功能崩溃✅ 新人优惠引发会员系统连环故障✅ 每次发布需全量回归测试根本原因:系统架构违反开闭原则开闭原则(Open-Closed Principle, OCP)(软件实体应对扩展开放,对修改关闭)在电商平台的后续重构中:✔️ 促销需求平均交付周期从2周缩短至3天✔️ 订单系统故障率下降76%✔️ 新入职开发者快速上手促销功能开发OCP不是束之高阁的理论,而是工程师每天都要面对的实践选择。

z2637305611的博客 1092

深入理解设计原则之开闭原则(OCP)【软件架构设计】

开闭原则(Open Closed Principle, OCP),又称为对扩展开放、对修改关闭原则。开闭原则即是SOLID原则中最难理解、最难掌握的,又是最有用的。之所以说开闭原则最难理解,是因为“怎样的代码改动才被定义为扩展?怎样代码的改动才被定义为修改?怎样才算满足或违反开闭原则?修改代码就一定意味着违反开闭原则吗?等问题都比较难理解。之所以说开闭原则最难掌握,是因为如何做到对扩展开放,对修改关闭?如何在项目中灵活应用开闭原则避免在追求高扩展的同时影响代码的可读性等问题都很难掌握。

weixin_30197685的博客 2347

开闭原则(OCP)

开闭原则 (OCP) 是面向对象编程中的一个基本原则,它指出应用程序实体(类、模块、方法等)应该对扩展开放但对修改关闭。换句话说,您应该能够在不更改现有代码的情况下向应用程序添加新功能。

sinat_26065899的博客 672
上一篇: 设计模式—— 五:迪米特原则
下一篇: 设计模式—— 七 :单例模式
加班不秃顶
博客等级 码龄7年 1822粉丝 599原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值