6大设计原则&23种设计模式
1、设计模式六大原则
1.1、单一职责
一个类只负责一项职责,应该仅有一个引起它变化的原因。
优点:
- 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多;
- 提高类的可读性,提高系统的可维护性;
- 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响。
1.2、里氏替换原则
子类可以扩展父类的功能,但不能改变父类原有的功能。即任何基类可以出现的地方,子类一定可以出现,并且当用子类替换了基类后程序不受影响。
含义:
- 子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法。
- 子类中可以增加自己特有的方法。
- 当子类的方法重载父类的方法时,方法的前置条件(即方法的形参)要比父类方法的输入参数更宽松。【注意区分重载和重写】
- 当子类的方法实现父类的抽象方法时,方法的后置条件(即方法的返回值)要比父类更严格。
1.3、依赖倒置原则
要求对抽象进行编程,不要对实现进行编程。
实际编程中需要做到:
- 低层模块尽量都要有抽象类或接口,或者两者都有。【可能会被人用到的】
- 变量的声明类型尽量是抽象类或接口。
- 使用继承时遵循里氏替换原则。
1.4、接口隔离原则
建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。
注意:
- 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度。
- 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系。
- 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情。
1.5、迪米特法则(最少知道原则)
一个对象应该对其他对象保持最少的了解。迪米特法则其根本思想,是强调了类之间的松耦合。
1.6、开闭原则
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
2、23种设计模式
2.1、设计模式的三种分类
- 创建型模式:对象实例化的模式,创建型模式用于解耦对象的实例化过程。
- 结构型模式:把类或对象结合在一起形成一个更大的结构。
- 行为型模式:类和对象如何交互,及划分责任和算法。
2.2、模式特点
-
单例模式:某个类只能有一个实例,提供一个全局的访问点。
-
饿汉式—静态常量方式(线程安全):
public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; } }
类加载时就初始化实例,避免了多线程同步问题。天然线程安全。
-
饿汉式—静态代码块方式(线程安全):
public class Singleton { private static Singleton instance; static { instance = new Singleton(); } private Singleton() {} public static Singleton getInstance() { return instance; } }
其实就是在上面 静态常量饿汉式 实现上稍微变动了一下,将类的实例化放在了静态代码块中而已。其他没区别。
-
懒汉式(线程不安全):
public class Singleton { private static Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }
这是最基本的实现方式,第一次调用才初始化,实现了懒加载的特性。多线程场景下禁止使用,因为可能会产生多个对象,不再是单例。
-
懒汉式(线程安全,方法上加同步锁):
public class Singleton { private static Singleton singleton; private Singleton() {} public static synchronized Singleton getInstance() { if (singleton == null) { singleton = new Singleton(); } return singleton; } }
和上面 懒汉式(线程不安全)实现上唯一不同是:获取实例的getInstance()方法上加了同步锁。保证了多线程场景下的单例。但是效率会有所折损,不过还好。
-
双重校验锁(线程安全,效率高):
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; } }
此种实现中不用每次需要获得锁,减少了获取锁和等待的事件。
注意volatile关键字的使用,保证了各线程对singleton静态实例域修改的可见性。 -
静态内部类实现单例(线程安全、效率高):
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
这种方式下 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。
注意内部类SingletonHolder要用static修饰且其中的静态变量INSTANCE必须是final的。
-
-
简单工厂:一个工厂类根据传入的参量决定创建出那一种产品类的实例。
-
工厂方法:定义一个创建对象的接口,让子类决定实例化那个类。
-
抽象工厂:创建相关或依赖对象的家族,而无需明确指定具体类。
-
建造者模式:封装一个复杂对象的构建过程,并可以按步骤构造。
-
原型模式:通过复制现有的实例来创建新的实例。
-
适配器模式:将一个类的方法接口转换成客户希望的另外一个接口。
-
组合模式:将对象组合成树形结构以表示“”部分-整体“”的层次结构。
-
装饰模式:动态的给对象添加新的功能。
-
代理模式:为其他对象提供一个代理以便控制这个对象的访问。
-
亨元(蝇量)模式:通过共享技术来有效的支持大量细粒度的对象。
-
外观模式:对外提供一个统一的方法,来访问子系统中的一群接口。
-
桥接模式:将抽象部分和它的实现部分分离,使它们都可以独立的变化。
-
模板模式:定义一个算法结构,而将一些步骤延迟到子类实现。
-
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器。
-
策略模式:定义一系列算法,把他们封装起来,并且使它们可以相互替换。
-
状态模式:允许一个对象在其对象内部状态改变时改变它的行为。
-
观察者模式:对象间的一对多的依赖关系。
-
备忘录模式:在不破坏封装的前提下,保持对象的内部状态。
-
中介者模式:用一个中介对象来封装一系列的对象交互。
-
命令模式:将命令请求封装为一个对象,使得可以用不同的请求来进行参数化。
-
访问者模式:在不改变数据结构的前提下,增加作用于一组对象元素的新功能。
-
责任链模式:将请求的发送者和接收者解耦,使的多个对象都有处理这个请求的机会。
-
迭代器模式:一种遍历访问聚合对象中各个元素的方法,不暴露该对象的内部结构。
本文来自博客园,作者:是老胡啊,转载请注明原文链接:https://www.cnblogs.com/solar-9527/p/15906418.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了