详解设计模式六大原则

Win11注册表没有MMC的解决方法 本文详细介绍了在Win11系统中解决注册表没有MMC项的问题的方法。通过创建并导入注册表修复文件,我们可以成功地在注册表中添加缺失的MMC项。在操作过程中,需要注意备份注册表、以管理员身份运行工具以及系统更新等事项。希望本文能够帮助到遇到类似问题的用户,提高系统管理的效率和便捷性。如果你还有其他关于Windows操作系统的问题或疑问,欢迎随时提问并寻求帮助。 阅读详情

设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。

借用并改编一下鲁迅老师《故乡》中的一句话,一句话概括设计模式: 希望本无所谓有,无所谓无.这正如coding的设计模式,其实coding本没有设计模式,用的人多了,也便成了设计模式

六大原则

设计模式(面向对象)有六大原则:

  • 开闭原则(Open Closed Principle,OCP)
  • 里氏代换原则(Liskov Substitution Principle,LSP)
  • 依赖倒转原则(Dependency Inversion Principle,DIP)
  • 接口隔离原则(Interface Segregation Principle,ISP)
  • 合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)
  • 最小知识原则(Principle of Least Knowledge,PLK,也叫迪米特法则)

开闭原则具有理想主义的色彩,它是面向对象设计的终极目标。其他几条,则可以看做是开闭原则的实现方法。 设计模式就是实现了这些原则,从而达到了代码复用、增加可维护性的目的。

 

C# 开闭原则

1.概念:

一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。模块应尽量在不修改原(是“原”,指原来的代码)代码的情况下进行扩展。

2.模拟场景:

在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。

3.Solution:

当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。

4.注意事项:

  • 通过接口或者抽象类约束扩展,对扩展进行边界限定,不允许出现在接口或抽象类中不存在的public方法
  • 参数类型、引用对象尽量使用接口或者抽象类,而不是实现类
  • 抽象层尽量保持稳定,一旦确定即不允许修改

5.开闭原则的优点:

  • 可复用性
  • 可维护性

6.开闭原则图解:

 

C# 里氏代换原则

1.概述: 派生类(子类)对象能够替换其基类(父类)对象被调用

2.概念:

里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。 LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。(源自百度百科)

3.子类为什么可以替换父类的位置?:

当满足继承的时候,父类肯定存在非私有成员,子类肯定是得到了父类的这些非私有成员(假设,父类的的成员全部是私有的,那么子类没办法从父类继承任何成员,也就不存在继承的概念了)。既然子类继承了父类的这些非私有成员,那么父类对象也就可以在子类对象中调用这些非私有成员。所以,子类对象可以替换父类对象的位置。

4.C# 里氏代换原则优点:

需求变化时,只须继承,而别的东西不会改变。由于里氏代换原则才使得开放封闭成为可能。这样使得子类在父类无需修改的话就可以扩展。

5.C# 里氏代换原则Demo:

代码正文:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

namespace TestApp

{

    using System;

 

    class Program

    {

        static void Main(string[] args)

        {

            Transportation transportation = new Transportation();

            transportation.Say();

            Transportation sedan = new Sedan();

            sedan.Say();

            Console.ReadKey();

        }

    }

 

    class Transportation

    {

        public Transportation()

        {

            Console.WriteLine("Transportation?");

        }

 

        public virtual void Say()

        {

            Console.WriteLine("121");

        }

    }

 

    class Sedan:Transportation

    {

        public Sedan()

        {

            Console.WriteLine("Transportation:Sedan");

        }

 

        public override void Say()

        {

            Console.WriteLine("Sedan");

        }

    }

 

    class Bicycles : Transportation

    {

        public Bicycles()

        {

            Console.WriteLine("Transportation:Bicycles");

        }

 

        public override void Say()

        {

            Console.WriteLine("Bicycles");

        }

    }

}

 

代码效果:

6.里氏代换原则图解:

 

C# 依赖倒转原则

1.概念:

依赖倒置原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

2.C# 依赖倒转原则用处:

有些时候为了代码复用,一般会把常用的代码写成函数或类库。这样开发新项目时,直接用就行了。比如做项目时大多要访问数据库,所以我们就把访问数据库的代码写成了函数。每次做项目去调用这些函数。那么我们的问题来了。我们要做新项目时,发现业务逻辑的高层模块都是一样的,但客户却希望使用不同的数据库或存储住处方式,这时就出现麻烦了。我们希望能再次利用这些高层模块,但高层模块都是与低层的访问数据库绑定在一起,没办法复用这些高层模块。所以不管是高层模块和低层模块都应该依赖于抽象,具体一点就是接口或抽象类,只要接口是稳定的,那么任何一个更改都不用担心了。

3.注意事项:

  • 高层模块不应该依赖低层模块。两个都应该依赖抽象。
  • 抽象不应该依赖结节。细节应该依赖抽象。

4.模拟场景:

场景:

假设现在需要一个Monitor工具,去运行一些已有的APP,自动化来完成我们的工作。Monitor工具需要启动这些已有的APP,并且写下Log。

代码实现1:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

namespace TestLibrary.ExtensionsClass

{

    using System;

 

    public class AppOne

    {

        public bool Start()

        {

            Console.WriteLine("1号APP开始启动");

            return true;

        }

 

        public bool ExportLog()

        {

            Console.WriteLine("1号APP输出日志");

            return true;

        }

    }

 

    public class AppTwo

    {

        public bool Start()

        {

            Console.WriteLine("2号APP开始启动");

            return true;

        }

 

        public bool ExportLog()

        {

            Console.WriteLine("2号APP输出日志");

            return true;

        }

    }

 

    public class Monitor

    {

        public enum AppNumber

        {

            AppOne=1,

            AppTwo=2

        }

 

        private AppOne appOne = new AppOne();

        private AppTwo appTwo = new AppTwo();

        private AppNumber number;

        public Monitor(AppNumber number)

        {

            this.number = number;

        }

 

        public bool StartApp()

        {

            return number == AppNumber.AppOne ? appOne.Start() : appTwo.Start();

        }

 

        public bool ExportAppLog()

        {

            return number == AppNumber.AppOne ? appOne.ExportLog() : appTwo.ExportLog();

        }

    }

}

代码解析1:

在代码实现1中我们已经轻松实现了Monitor去运行已有APP并且写下LOG的需求。并且代码已经上线了.

春…夏…秋…冬…

春…夏…秋…冬…

春…夏…秋…冬…

就这样,三年过去了。

一天客户找上门了,公司业务扩展了,现在需要新加3个APP用Monitor自动化。这样我们就必须得改Monitor。

代码实现2:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

namespace TestLibrary.ExtensionsClass

{

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

 

    public class Monitor

    {

        public enum AppNumber

        {

            AppOne = 1,

            AppTwo = 2,

            AppThree = 3,

            AppFour = 4,

            AppFive = 5

        }

 

        private AppOne appOne = new AppOne();

        private AppTwo appTwo = new AppTwo();

        private AppThree appThree = new AppThree();

        private AppFour appFour = new AppFour();

        private AppFive appFive = new AppFive();

        private AppNumber number;

        public Monitor(AppNumber number)

        {

            this.number = number;

        }

 

        public bool StartApp()

        {

            bool result = false;

            if (number == AppNumber.AppOne)

            {

                result = appOne.Start();

            }

            else if (number == AppNumber.AppTwo)

            {

                result = appTwo.Start();

            }

            else if (number == AppNumber.AppThree)

            {

                result = appThree.Start();

            }

            else if (number == AppNumber.AppFour)

            {

                result = appFour.Start();

            }

            else if (number == AppNumber.AppFive)

            {

                result = appFive.Start();

            }

 

            return result;

        }

 

        public bool ExportAppLog()

        {

            bool result = false;

            if (number == AppNumber.AppOne)

            {

                result = appOne.ExportLog();

            }

            else if (number == AppNumber.AppTwo)

            {

                result = appTwo.ExportLog();

            }

            else if (number == AppNumber.AppThree)

            {

                result = appThree.ExportLog();

            }

            else if (number == AppNumber.AppFour)

            {

                result = appFour.ExportLog();

            }

            else if (number == AppNumber.AppFive)

            {

                result = appFive.ExportLog();

            }

 

            return result;

        }

    }

}

代码解析2:

这样会给系统添加新的相互依赖。并且随着时间和需求的推移,会有更多的APP需要用Monitor来监测,这个Monitor工具也会被越来越对的if…else撑爆炸,而且代码随着APP越多,越难维护。最终会导致Monitor走向灭亡(下线)。

介于这种情况,可以用Monitor这个模块来生成其它的程序,使得系统能够用在需要的APP上。OOD给我们提供了一种机制来实现这种“依赖倒置”。

代码实现3:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

namespace TestLibrary.ExtensionsClass

{

    using System;

 

    public interface IApp

    {

        bool Start();

        bool ExportLog();

    }

 

    public class AppOne : IApp

    {

        public bool Start()

        {

            Console.WriteLine("1号APP开始启动");

            return true;

        }

 

        public bool ExportLog()

        {

            Console.WriteLine("1号APP输出日志");

            return true;

        }

    }

 

    public class AppTwo : IApp

    {

        public bool Start()

        {

            Console.WriteLine("2号APP开始启动");

            return true;

        }

 

        public bool ExportLog()

        {

            Console.WriteLine("2号APP输出日志");

            return true;

        }

    }

 

    public class Monitor

    {

        private IApp iapp;

        public Monitor(IApp iapp)

        {

            this.iapp = iapp;

        }

 

        public bool StartApp()

        {

            return iapp.Start();

        }

 

        public bool ExportAppLog()

        {

            return iapp.ExportLog();

        }

    }

}

代码解析3:

现在Monitor依赖于IApp这个接口,而与具体实现的APP类没有关系,所以无论再怎么添加APP都不会影响到Monitor本身,只需要去添加一个实现IApp接口的APP类就可以了。

 

C# 接口隔离原则

1.概念:

客户端不应该依赖它不需要的接口,类间的依赖关系应该建立在最小的接口上

2.含义:

接口隔离原则的核心定义,不出现臃肿的接口(Fat Interface),但是“小”是有限度的,首先就是不能违反单一职责原则。

3.模拟场景:

一个OA系统,外部只负责提交和撤回工作流,内部负责审核和驳回工作流。

4.代码演示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

namespace TestLibrary.ExtensionsClass

{

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

 

    public interface IReview

    {

        void ReviewWorkFlow();

 

        void RejectWorkFlow();

    }

 

    public class Review : IReview

    {

        public void ReviewWorkFlow()

        {

            Console.WriteLine("开始审核工作流");

        }

 

        public void RejectWorkFlow()

        {

            Console.WriteLine("已经驳回工作流");

        }

    }

 

    public interface ISubmit

    {

        void SubmitWorkFlow();

 

        void CancelWorkFlow();

    }

 

    public class Submit : ISubmit

    {

        public void SubmitWorkFlow()

        {

            Console.WriteLine("开始提交工作流");

        }

 

        public void CancelWorkFlow()

        {

            Console.WriteLine("已经撤销工作流");

        }

    }

}

5.代码解析:

其实接口隔离原则很好理解,在上面的例子里可以看出来,如果把OA的外部和内部都定义一个接口的话,那这个接口会很大,而且实现接口的类也会变得臃肿。

 

C# 合成/聚合复用原则

1.概念:

合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)经常又叫做合成复用原则。合成/聚合复用原则就是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。它的设计原则是:要尽量使用合成/聚合,尽量不要使用继承。

2.合成/聚合解析:

聚合概念:

聚合用来表示“拥有”关系或者整体与部分的关系。代表部分的对象有可能会被多个代表整体的对象所共享,而且不一定会随着某个代表整体的对象被销毁或破坏而被销毁或破坏,部分的生命周期可以超越整体。例如,Iphone5和IOS,当Iphone5删除后,IOS还能存在,IOS可以被Iphone6引用。

聚合关系UML类图:

C# 合成/聚合复用原则

代码演示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

namespace TestLibrary.ExtensionsClass

{

    class IOS

    {

    }

 

    class Iphone5

    {

        private IOS ios;

        public Iphone5(IOS ios)

        {

            this.ios = ios;

        }

    }

}

合成概念:

合成用来表示一种强得多的“拥有”关系。在一个合成关系里,部分和整体的生命周期是一样的。一个合成的新对象完全拥有对其组成部分的支配权,包括它们的创建和湮灭等。使用程序语言的术语来说,合成而成的新对象对组成部分的内存分配、内存释放有绝对的责任。一个合成关系中的成分对象是不能与另一个合成关系共享的。一个成分对象在同一个时间内只能属于一个合成关系。如果一个合成关系湮灭了,那么所有的成分对象要么自己湮灭所有的成分对象(这种情况较为普遍)要么就得将这一责任交给别人(较为罕见)。例如:水和鱼的关系,当水没了,鱼也不可能独立存在。

合成关系UML类图:

代码演示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

namespace TestLibrary.ExtensionsClass

{

    using System;

 

    class Fish

    {

        public Fish CreateFish()

        {

            Console.WriteLine("一条小鱼儿");

            return new Fish();

        }

    }

 

    class Water

    {

        private Fish fish;

        public Water()

        {

            fish = new Fish();

        }

 

        public void CreateWater()

        {

            // 当创建了一个水的地方,那这个地方也得放点鱼进去

            fish.CreateFish();

        }

    }

}

3.模拟场景:

比如说我们先摇到号(这个比较困难)了,需要为自己买一辆车,如果4S店里的车默认的配置都是一样的。那么我们只要买车就会有这些配置,这时使用了继承关系:

不可能所有汽车的配置都是一样的,所以就有SUV和小轿车两种(只列举两种比较热门的车型),并且使用机动车对它们进行聚合使用。这时采用了合成/聚合的原则:

 

C# 迪米特法则

1.概念:

一个软件实体应当尽可能少的与其他实体发生相互作用。每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位。迪米特法则的初衷在于降低类之间的耦合。由于每个类尽量减少对其他类的依赖,因此,很容易使得系统的功能模块功能独立,相互之间不存在(或很少有)依赖关系。迪米特法则不希望类之间建立直接的联系。如果真的有需要建立联系,也希望能通过它的友元类来转达。因此,应用迪米特法则有可能造成的一个后果就是:系统中存在大量的中介类,这些类之所以存在完全是为了传递类之间的相互调用关系——这在一定程度上增加了系统的复杂度。

2.模拟场景:

场景:公司财务总监发出指令,让财务部门的人去统计公司已发公司的人数。

一个常态的编程:(肯定是不符LoD的反例)

UML类图:

代码演示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

namespace TestLibrary.ExtensionsClass

{

    using System;

    using System.Collections.Generic;

 

    /// <summary>

    /// 财务总监

    /// </summary>

    public class CFO

    {

        /// <summary>

        /// 财务总监发出指令,让财务部门统计已发工资人数

        /// </summary>

        public void Directive(Finance finance)

        {

            List<Employee> employeeList = new List<Employee>();

            // 初始化已发工资人数

            for (int i = 0; i < 500; i++)

            {

                employeeList.Add(new Employee());

            }

 

            // 转告财务部门开始统计已结算公司的员工

            finance.SettlementSalary(employeeList);

        }

    }

 

    /// <summary>

    /// 财务部

    /// </summary>

    public class Finance

    {

        /// <summary>

        /// 统计已结算公司的员工

        /// </summary>

        public void SettlementSalary(List<Employee> employeeList)

        {

            Console.WriteLine(string.Format("已结算工资人数:{0}", employeeList.Count));

        }

    }

 

    /// <summary>

    /// 员工

    /// </summary>

    public class Employee

    {

 

    }

 

    /// <summary>

    /// 主程序

    /// </summary>

    public class Runner

    {

        public static void main(String[] args)

        {

            CFO cfo = new CFO();

            // 财务总监发出指令

            cfo.Directive(new Finance());

        }

    }

}

根据模拟的场景:财务总监让财务部门总结已发工资的人数。 财务总监和员工是陌生关系(即总监不需要对员工执行任何操作)。根据上述UML图和代码解决办法显然可以看出,上述做法违背了LoD法则。

依据LoD法则解耦:(符合LoD的例子)

UML类图:

代码演示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

namespace TestLibrary.ExtensionsClass

{

    using System;

    using System.Collections.Generic;

 

    /// <summary>

    /// 财务总监

    /// </summary>

    public class CFO

    {

        /// <summary>

        /// 财务总监发出指令,让财务部门统计已发工资人数

        /// </summary>

        public void Directive(Finance finance)

        {

            // 通知财务部门开始统计已结算公司的员工

            finance.SettlementSalary();

        }

    }

 

    /// <summary>

    /// 财务部

    /// </summary>

    public class Finance

    {

        private List<Employee> employeeList; 

 

        //传递公司已工资的人

        public Finance(List<Employee> _employeeList)

        {

            this.employeeList = _employeeList; 

    } 

 

        /// <summary>

        /// 统计已结算公司的员工

        /// </summary>

        public void SettlementSalary()

        {

            Console.WriteLine(string.Format("已结算工资人数:{0}", employeeList.Count));

        }

    }

 

    /// <summary>

    /// 员工

    /// </summary>

    public class Employee

    {

 

    }

 

    /// <summary>

    /// 主程序

    /// </summary>

    public class Runner

    {

        public static void main(String[] args)

        {

            List<Employee> employeeList = new List<Employee>();

 

            // 初始化已发工资人数

            for (int i = 0; i < 500; i++)

            {

                employeeList.Add(new Employee());

            }

 

            CFO cfo = new CFO();

 

            // 财务总监发出指令

            cfo.Directive(new Finance(employeeList));

        }

    }

}

根据LoD原则我们需要让财务总监和员工之间没有之间的联系。这样才是遵守了迪米特法则。

 

博客总结

想搞懂设计模式,必须先知道设计模式遵循的六大原则,无论是哪种设计模式都会遵循一种或者多种原则。这是面向对象不变的法则。本文针对的是设计模式(面向对象)主要的六大原则展开的讲解,并尽量做到结合实例和UML类图,帮助大家理解。在后续的博文中还会跟进一些设计模式的实例。

Statistics and Machine Learning Toolbox Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具 立即下载

相关推荐

行政数据分析大屏实战:用Tableau从Excel到看板的完整搭建流程(含数据连接与字段计算避坑)

本文详细介绍了如何利用Tableau从Excel数据源搭建行政数据分析大屏的完整流程,涵盖数据准备、连接技巧、计算字段优化、看板设计及动态交互部署。通过五阶工作流,帮助用户高效处理多源异构数据,实现业务洞察与可视化呈现,提升行政数据分析效率。

weixin_29696711的博客 342

六大设计原则详解

在学习设计模式之前,我们需要先了解设计原则,依据设计原则衍生出23种常见的设计模式,在做顶层架构设计的时候须依据设计原则去做架构设计,遵照高内聚、低耦合,单一职责等原则有意识的对后期的业务架构设计支撑扩展和降低耦合影响。

橙子的随笔集 564

5.1 滑模控制(SMC)及其改进

本文系统阐述了滑模控制(SMC)的基本原理及其在永磁同步电机(PMSM)控制系统中的应用。首先介绍了滑模控制的核心思想,包括滑模面设计和不连续控制律,其强鲁棒性使其在电机控制领域得到广泛应用。其次分析了SMC在PMSM速度控制器和无位置传感器观测器中的具体实现方案。重点探讨了SMC固有的抖振问题,详细比较了边界层法、高阶滑模和自适应方法等多种改进策略的优缺点。最后指出改进SMC的研究趋势是多种策略的融合应用,如自适应高阶滑模等,以在保持鲁棒性的同时有效抑制抖振。

技术工作者 1450

设计模式(一)——六大原则

设计模式六大原则

m0_47743175的博客 3837

COMSOL两相流(相场法)

COMSOL是一款功能非常强大的多物理场仿真软件,拥有可视化和后处理工具,可方便有效的展示您的仿真效果,具有灵活、高效、友好的特点,软件能够为用户提供各类工程问题的解决方案,从而帮助广大研究和工程人员能够在科研上取得新突破。 COMSOL可以实现声学、传热、流体力学、结构力学等方面的模拟仿真,具体模块如下图所示。 COMSOL软件设置流程 定义需要求解的问题类型:针对一个需要仿真的问题,需要先对问题进行分析;分析该问题用到哪些物理场,什么样的几何模型,以及如何设置研究等。该步骤可以使用COMSOL中的

weixin_47139559的博客 1万+

学习STM32的流体水位传感器

引言: 流体水位传感器是一种常用于测量液体水位的设备,广泛应用于水位监测、液位控制和流量计量等领域。STM32是一款功能强大的单片机,具有丰富的外设和灵活的编程能力,非常适合用于流体水位传感器的开发。本文将介绍如何使用STM32开发板与流体水位传感器进行连接和通信,并通过编写代码实现水位的测量和显示。五、总结: 通过以上的代码示例,我们可以实现使用STM32开发板与流体水位传感器进行连接和通信的功能。三、编写代码: 以下是使用STM32CubeIDE编写的示例代码,实现了读取流体水位传感器的功能。

xiaoalla的博客 740

设计模式六大原则

文章目录软件设计的六大原则1. 开放-封闭原则2. 单一职责原则举例3. 里氏替换原则4. 依赖倒置原则举例5. 接口隔离原则6. 迪米特原则举例 软件设计的六大原则 设计模式的六大原则 参考URL: https://zhuanlan.zhihu.com/p/92152190 1. 开放-封闭原则 Open-Close Principle(OCP):一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。目的就是保证程序的扩展性好,易于维护和升级。 对于扩展是开放的,对于更改是封闭的。 开放-封闭原则是面向

西京刀客 1万+

Java 部分笔试题解析

合法的 try 语句块必须包含 try 块,并且至少包含一个 catch 块或一个 finally 块。给定一个长度为n的数组,数组中的每个元素,表示一根水管的长度,水管可以在任意位置锯开。调用 sleep() 方法、创建新线程、高优先级线程进入就绪状态只会暂停或抢占线程的执行,而不会终止线程的运行。A.抽象类中可以包含非抽象的普通方法,接口中的方法必须是抽象的,不能有非抽象的普通方法。接口中的成员变量必须是常量(static final),而抽象类可以有普通成员变量。

博客 2579

设计模式——类与对象设计的六大基本原则

本文介绍了设计模式中的六大基本原则:单一职责原则、开放封闭原则、子类替换父类原则、接口调用原则、类对象交互原则和接口隔离原则。通过具体代码示例,阐述了每个原则的核心思想和应用场景,旨在提高代码的可维护性和灵活性。

庄小焱 6191

msfvenom制作windows/linux/android/ios木马

msfvenom选项如下 -p, --payload<payload> 指定 payload(攻击荷载)。如果使用自定义payload,请使用'-'或者stdin指定。 -l, --list [module_typel列出指定模块的所有可用资源。模块类型包括:payloads, encoders, nops, all -n, --nopsled <length>为payload预先指定一个NOP滑动长度。 -f, --format <format>指定输出格式(使

Cwillchris的博客 2734

ADAS工作原理解析:如何通过智能技术提升驾驶安全

ADAS通过集成传感器、摄像头、雷达、SoC计算单元以及高效的数据融合技术,提供了一系列主动和被动安全功能,如自动刹车、车道保持、自适应巡航控制等。这些功能共同作用,不仅减少了交通事故的发生,还大幅提升了驾驶员的驾驶体验和安全性。随着技术的进步,ADAS的功能将越来越智能,最终迈向全自动驾驶的未来🚗💨。

weixin_43199439的博客 1149

设计模式六大原则详解

类的功能应当尽可能单一化,如果一个类承担了多个职责,则当其中一个职责发生变化时,可能会影响到其他职责,从而导致代码难以维护。: 如果一个程序使用的是父类的一个对象,那么用子类的对象来替换它时,程序的行为不应该发生任何变化。: 当应用程序的需求改变时,可以通过增加新的代码来满足新需求,而不是修改现有的代码。: 接口中定义的方法应该尽可能地具体,以避免出现客户端不需要使用的方法。: 软件实体(类、模块、函数等)应该是可以扩展的,但是不可修改的。: 每个类都应当减少对外部类的依赖,只与直接的朋友通信。

weixin_43298211的博客 1102

nRF52832——大量数据传输时导致蓝牙断开连接,且无法被搜索到的解决方案(广播参数的设置、程序设计方法)

有时蓝牙通信单次发送数据量较大,且连续发送多次的时候,你会发现蓝牙就会出现异常,可能运行30min,40min,或者1h后,蓝牙就不能传输数据了,且无法被搜索到,用主机扫描蓝牙时可能会提示类似这样的DEBUG信息:bta_gattc_mark_bg_conn unable to find the bg connection mask for bd_addr=xx:xx:xx:xx:xx:xx。

数字世界 万物互联 2006

【设计模式】六大原则详解

ps:写到这里, 我明显感觉我的思考问题的方式在发生着改变, 我们的代码, 应该遵循的一些规范, 往往在人们的生活方式改变的同时改变着, 代码离不开生活, 美好的生活由代码构成, 在今后的社会, 有可能我们的代码就像是科学一样, 人人都应该了解她, 学习她.这样简单明朗,意思深刻 ,当然这些都是我抄的大神的, 有时候没有必要自己写一些代码, 跟着前辈走, 带你少走很多弯路, 有时候总是走自己的路, 尽管得到的更多, 但是并不是每个人都是这样的, 我是前者, 我明白自己的短板.

沙师弟专栏 1580

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

深度学习工具包 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")

【设计模式】六大原则详解,每个原则提供代码示例

设计模式的六大原则是面向对象设计中的基本准则,它们有助于编写灵活、可维护、可扩展的代码。这六大原则分别是:单一职责原则(Single Responsibility Principle,SRP)、开放封闭原则(Open/Closed Principle,OCP)、里氏替换原则(Liskov Substitution Principle,LSP)、依赖倒置原则(Dependency Inversion Principle,DIP)、接口隔离原则(Interface Segregation Principle)

摸鱼小小虫的博客 1898

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

设计模式的六大原则详解与应用

在软件开发过程中,**设计模式**帮助开发者创建更高效、灵活且可维护的代码。设计模式不仅仅是一些常见的解决方案,更是一套抽象思维方式,帮助我们设计出符合软件工程原则的架构。设计模式的基础是六大原则,这些原则指引我们如何设计出高内聚、低耦合的代码结构,减少复杂度,增加系统的扩展性和维护性。 本文将详细介绍设计模式中的**六大设计原则**,包括其核心概念、实际应用场景以及每个原则在软件开发中的重要性。

fudaihb的博客 1223

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

设计模式六大原则及常用模式详解

设计模式六大原则 1、单一职责原则(Single Responsibility Principle) 定义 : 应该有且只有一个原因引起类的变化 注意 : 这里的类不光指类,也适用于方法和接口,比如我们常说的一个方法实现一个功能 2、里氏代换原则(Liskov Substitution Principle) 定义 : 只要父类出现的地方子类就一定可以出现,而且替换为子类也不会出现任何异常或错误,使...

小生的博客 1549

设计模式六大原则 — 列举反例详解各个原则的核心思想和意义

设计模式的六大原则是面向对象设计的基石,遵循这些原则可以提升代码的可维护性、可扩展性和可读性。下面对六大原则进行详细解析。一个类只负责一项职责。软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。所有引用基类的地方必须能透明地使用其子类的对象。客户端不应该依赖它不需要的接口,一个类对另一个类的依赖应建立在最小接口上。高层模块不应依赖低层模块,二者都应依赖抽象抽象不应依赖细节,细节应依赖抽象一个对象应该对其他对象保持最少的了解,只与直接朋友通信。原则核心思想关键点单一职责原则 (SRP)

csdn_silent的博客 3312

设计模式-六大原则详解

设计模式它是一种代码编程长期发展的经验和解决某种问题的通用的思想,并且中所周知的一套代码方法和理念。也是我们编写程序的基石。我日常写代码就好比建造房子一样,首先我们需要搭建好架子。然后根据这个架子慢慢的将整个大厦建起来。同样的,我们在编写程序的时候,也需要遵循一定的原则和框架,这样我们写出来的程序才更见健壮,开发起来也会更加省时间,提高代码的可读性,拓展性,重用性,灵活性等,减少开发成本。设计模式...

rianple的博客 359

Java设计模式六大原则详解

也有人会将"合成复用原则"(Composition/Aggregation Reuse Principle,CARP)视为Java设计模式的第七大原则,但它其实是“里氏替换原则”和“开闭原则”的延伸和具体化。也就是说,在修改已有代码的情况下,尽量不要修改原有的代码,而是通过扩展来实现功能的增加。(Law of Demeter,LoD):一个对象应该对其他对象有尽可能少的了解,不和陌生人说话。也就是说,一个对象应该尽量减少对其它对象的依赖和交互,只依赖于那些真正需要交互的对象。

TyquanChen的博客 311
上一篇: 详解设计模式六大原则
下一篇: 谈一谈自己对依赖、关联、聚合和组合之间区别的理解
秋夜无霜
博客等级 码龄16年 137粉丝 100原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值