大话设计模式——设计原则单例模式(UML类图)
Posted 苍山有雪,剑有霜
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大话设计模式——设计原则单例模式(UML类图)相关的知识,希望对你有一定的参考价值。
设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样。只有精通了设计模式,才敢说真正理解了软件工程。可以说,设计模式是每一个架构师所必备的技能之一。
PS:虽然本文代码是基于Java(但学习设计模式不拘泥于设计模式,不管是何种面向对象语言,甚至是非OO语言,我觉得都能从设计模式中窥探一丝代码架构的奥秘),主要来源于《Head First 设计模式》这本书,并附上了详细的代码,强烈建议大家仔细阅读源代码。
在本文中不会列出全部的代码,重点集中在解释什么是设计模式?什么场景下可以用这种设计模式?尝试以实际的问题来驱动学习,使得我们对设计模式的理解更为深刻而具体。
让我们一起来学习设计模式吧!
前言
关于面向对象特性,在《大话设计模式》中有一段极其生动的讲解,面向对象就得像活字印刷术一样:
第一,要改,只需更改要改之字,此为可维护;第二,这些字并非用完这次就无用,完全可以在后来的印刷中重复使用,此乃可复用;第三,此诗若要加字,只需另刻字加入即可,这是可扩展;第四,字的排列其实可能是竖排可能是横排,此时只需将活字移动就可做到满足排列需求,此是灵活性好。
设计原则
想要精通设计模式,必须要先搞清楚设计模式的设计原则。
- 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起!——也可以说类应该对扩展开放,对修改关闭,简称开放封闭原则
PS:怎么看什么是“变化”?——如果每次需求一来,某个部分就必须改变,那么就是不稳定变化的代码。
- 针对接口编程,而不是针对实现编程。——也可以说要依赖抽象,不要依赖具体类,简称依赖倒置原则
PS:针对接口编程,其实是”面向超类型(抽象类、接口)“编程。这个原则让编程的细节被隐藏,不会因为修改具体实现而经常改动程序结构。
- 多用组合,少用继承。
PS:虽然继承接口可以让不同子类中实现方式不同,但是接口不具有复用性(每一个接口的实现代码都得重写),而组合却可以为后续的程序设计提供便利。
- 为了交互对象之间的松耦合设计而努力
PS:交互对象之间应尽可能的松耦合,以应对后期项目业务逻辑变动的风险。
- 一个类对自己依赖的类知道的越少越好,简称最少知识原则。(亦称得墨特尔法则)
PS:一旦某个类应该只与它必须知道的类去交互,而不应该知道其他的类,编程的总原则就是高聚合,低耦合。
- 一个类应该只有一个引起变化的原因,单一职责原则。
PS:不应该存在多于一个导致类变更的原因,如若不然,就应该将类拆分。
UML类图
为了在之后的学习中更好地理解设计模式,我们需要先学习一下如何绘制、阅读UML类图。
为了更好地理解这本书的例子,需要先对UNL类图进行简单的学习。大部分的关系都在下面这幅图里面了,多看并记忆即可:
对于类中字段和方法:+ 表示public;-表示private;#表示protected;
继承关系用空心三角加实线;
接口关系用空心三角加虚线;
关联关系(如上图企鹅和气候,企鹅需要了解气候)用实线箭头;
PS:关联可以看成是,某个类中含有其他某类的对象。
聚合关系(大雁和雁群,是一种弱拥有关系)用空心菱形和实线箭头;
合成(组合)关系(鸟和翅膀是强拥有,即整体和局部的关系)用实心菱形和实线箭头,两端的底下的数字,表示几对几的关系;
依赖关系(某个类需要基于某个类而存在)用虚线箭头;
绘制UML类图,可以使用Visio或者Drawio。
设计原则是编程设计过程中需要时刻考虑的,近乎于道,这些设计原则的组合、碰撞,就产生了许多精彩绝伦、可用性极强的设计模式,是可以用的术。之所以称为模式,是因为在日常的编程开发中,我们都可以学习、借鉴它们。接下来对设计模式的介绍,我会从:定义、场景、解决的方式方便大家的理解。
单例模式
定义
单例模式确保一个类只有一个实例,并提供一个全局访问点。
这定义已经很明确了,那就是全局只能有这个类的一个实例。
场景
单例模式可以说大家都有所耳闻,甚至实际开发中也用到过(Spring中的组件Bean就是一个一个的单例),当你需要控制某个类的实例数量时,就需要使用单例模式了。
解决
那么如何让全局只有一个类呢?
——简单,将构造函数声明为private,这样就不能在外部通过new来实现了。
问题来了,既然构造函数已经被声明为private,怎么获得该类的对象呢?
——简单,在该类的内部声明一个静态成员函数即可。
单例模式的实现分为懒汉、饿汉模式。
饿汉模式:类初始化的时候就建立该类的一个实例:
public class SingleObject {
//创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
private SingleObject(){}
//可以通过该API获取唯一可用的对象
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
懒汉模式:知道其他类需要该实例的时候才创建对应的实例:
public class Singleton {
private static Singleton instance;
private Singleton (){}
//需要的时候再创建对应的实例
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
考虑到线程安全,可以改为:
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
//采用双检查锁,避免频繁加锁,性能较好
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
参考资料
《大话设计模式》
《Head First 设计模式》
https://www.huaweicloud.com/articles/d5883e90e6f48d77fe6967775337093b.html
项目地址
https://github.com/white0dew/Design-pattern/tree/master
其他文章
https://mp-new.csdn.net/
https://blog.csdn.net/ll15982534415/article/details/117337900
以上是关于大话设计模式——设计原则单例模式(UML类图)的主要内容,如果未能解决你的问题,请参考以下文章