1、设计模式的种类
- 创建型模式:
单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式 - 结构型模式:
适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式,代理模式 - 行为型模式:
模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、接解释器模式、状态模式、策略模式、职责链模式、访问者模式。
2、OOP七大法则
- 开闭原则:对扩展开放,对修改关闭。
- 里氏替换原则:继承必须确保超类所拥有的性质在子类中仍然成立。
- 依赖倒置原则:要面向接口编程,不要面向实现编程。
- 单一职责原则:控制类的粒度大小、将对象解耦、提高其内聚性。
- 接口隔离原则:要为各个类建立他们需要专用接口。
- 迪米特法则:只与你的朋友直接交谈,不跟陌生人说话。
- 合成复用原则:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
注:在项目中改动别人的代码是大忌
3、单例模式
单例模式便是创建型设计模式的一种,它确保某一个类在系统中只有一个实例,并自行实例化,同时向外部提供获取这个唯一实例的接口。
- 设计思想:
- 避免因创建多个实例而导致的调用错误,单例模式保证使整个项目访问的是同一个实例
- 减少内存开销
- 单例模式的三大特性:
- 单例类只有一个实例。
- 单例类必须自己实例化自己。
- 单例类需要向外提供实例。
- 解决思路:
- 其他程序不能new该对象
- 在该类中创建本类对象属性
- 对外提供统一的获取对象方法
- 目的
- 私有化构造函数------------------------------------------不能被实例化
- 在本类中创建一个本类对象的属性-----------------------创建统一的调用属性
- 定义一个公有的方法,返回创建的本类对象-------------提供统一的对象入口
-
访问方式:
Singleton instance = Singleton.getInstance(); 通过公有的方法访问统一的对象 -
常用场景:工具类、线程池、缓存、数据库、账户登录系统、配置文件等程序中
3.1、饿汉式
public class Singleton {
private static Singleton instance=new Singleton(); //提供统一对象
private Singleton(){}; //私有化构造函数
public static Singleton getInstance(){ //提供统一入口
return instance;
}
}
//优点:实现简单,类加载时实例化,避免了线程同步的问题。
//缺点:类加载时实例化,创建了可能用不到的对象,没有达到懒加载的效果。造成资源浪费(可以忽略)
//懒加载:不加载用不到的信息
3.2、懒汉式
public class Singleton {
private static Singleton instance=null;
private Singleton() {};
public static Singleton getInstance(){
if(instance==null){
instance=new Singleton();
}
return instance;
}
}
//优点:需要时才去创建实例
//缺点:没有考虑线程安全问题,多个线程并发调用时可能会创建多个实例(违背了单例模式原则)
//解决懒汉模式线程安全问题:在方法上加上锁 synchronized 但是内存消耗比较大,不推荐
3.3、懒汉式双重校验锁
public class Singleton {
/**
* 懒汉式变种,属于懒汉式中最好的写法,保证了:延迟加载和线程安全
*/
private static volatile Singleton instance=null; //volatile 解决指令重排序
private Singleton() {};
public static Singleton getInstance(){
if (instance == null) { //一重
synchronized (Singleton.class) { //锁类对象
if (instance == null) { //两重
instance = new Singleton();
}
}
}
return instance;
}
}
//优点: 性能高了,线程安全了
//缺点:可读性难度加大,不够优雅
3.4、静态内部类
public class Singleton{
private Singleton();
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.INSTANCE;
}
}
原理:
- JVM在加载外部类的时候并不会加载其静态内部类,在使用到静态内部类的时候才会对静态内部类进行加载。类的静态变量是在类加载的时候进行加载的,这样静态内部类实现单例模式就有一个特性:如果没有使用到这个实例,这个实例就不会进行加载。这和懒汉模式一样,能有效节省资源。
- JVM底层保证类加载的安全,即使在高并发的情况下,类的加载都只有一次,这就保证了创建单例时的并发安全性。
3.5、枚举
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
原理:
枚举中的各个枚举项同时通过static来定义的,保证了线程安全问题
缺点:反序列化会破坏单例的问题。
4、工厂模式
实现了生产者和消费者的分离
4.1、简单工厂模式
用来生产同一等级结构中的任意产品(对于增加新的产品,需要覆盖已有代码)
- 特点
- 有一个重要的create()方法,利用if或者 switch创建产品并返回。
- create()方法通常是静态的,所以也称之为静态工厂。
- 缺点
- 扩展性差(静态方法不能被继承和重写,我想增加一种产品,除了新增一个产品类,还需要修改工厂类方法)
- 不同的产品需要不同额外参数的时候 不支持。
- 违背“开闭原则”
4.2、工厂方法模式
多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。
- 使用步骤:
步骤1: 创建抽象工厂接口,定义具体工厂的公共接口;
步骤2: 创建抽象产品接口 ,定义具体产品的公共接口;
步骤3: 创建具体产品类(继承抽象产品接口), 定义生产的具体产品;
步骤4:创建具体工厂类(继承抽象工厂接口),定义创建对应具体产品实例的方法;
步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例 - 优点
- 更符合开-闭原则
- 符合单一职责原则
- 不使用静态工厂方法,可以形成基于继承的等级结构。
结构复杂度:简单工厂优
代码复杂度:简单工厂优
编程复杂度:简单工厂优
管理复杂度:简单工厂优
设计原则上:工厂方法优
实际业务上:简单工厂多
注:并不是所有设计都要满足设计原则,因为会导致系统过于复杂,具体情况具体分析
4、抽象工厂模式(超级工厂创建产品系列工厂)
- 定义:抽象工厂模式提供了一个创建一系列相关或相互依赖对象的
接口
,无需指定它们具体的类。 - 使用场景:
- 客户端不依赖于产品类实例如何被创建,实现等细节
- 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码
- 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现
- 优点:
1. 具体产品在应用层的代码隔离,无需关系创建的细节
2. 将一个系列的产品统一到一起创建 - 缺点:
- 规定了所有可能被创建的产品集合,不易于扩展产品簇。
- 增加了系统的抽象性和理解难度
5、建造者模式
- 定义:将一个复杂下的构建于他的表示分离,使得
同样的构建过程
可以创建不同的表示
- 主要作用:咋用户不知道 对象的建造过程的细节 的情况下就可以直接创建复杂的对象
- 用户只需要给出指定的对象类型和内容,建造者模式负责按顺序创建复杂对象(把内部额建造过程和细节隐藏起来)
角色分析:
指挥者:控制调用的先后顺序
- 监视者模式:有指挥者角色,负责指挥工人执行工人按照顺序建造;(规定工人执行方法的顺序)
- 匿名模式:无指挥者角色,由调用者(消费者)选择(可采用链式编程改变产品属性值和工人执行顺序)
工人(抽象的):工人能做的事情(抽象方法)
工人实现:工人执行方法的具体实现
产品: 最后被创建的对象
- 优点:
- 产品的建造和表示分离,实现了解耦,使用建造者模式,可以使客户端不必知道产品内部组成的细节。
- 将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰。
- 具体的建造者类之间是相互独立的,这有利于系统的扩展。增加新的具体建造者无需修改原有类库的代码,符合”
开闭原则
“
- 缺点:
- 建造者模式所创建的产品一般具有较多的共同点(属性或方法),组成部分相似。如果产品间差异性很大,则不适合使用建造者模式。因此其使用范围受到一定的限制。
- 如果产品内部的变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统庞大。
建造者与抽象工厂模式的比较
- 返回内容不同:
- 建造者模式:返回一个完整的产品
- 抽象工厂模式:返回一系列相关的产品,这些产品构成一个产品族
- 获取产品方式:
- 建造者模式:可以不直接调用建造者模式,可以通过静态代理指挥者,有指挥者控制产品对象的生成(方法实现内容及顺序),返回一个完整产品。
- 抽象工厂模式:需要实例化工厂,调用工厂方法获取所需产品对象。
6、原型模式
- 克隆
- Prototype //原型
- Cloneable接口
- clone() 方法 (调用本地的C++方法)
6.1、浅克隆(浅拷贝)
实现流程:
- 被克隆对象
实现Cloneable接口
,重写clone() 方法 - 实例化后的克隆对象调用clone() 方法(返回值是Object对象需要强转)
特点:
3. 克隆对象与被克隆对象 内存中指向同一数据(共享数据源,拷贝了引用地址)
4. hash值不同
6.2、深克隆(深拷贝)
实现方案:
- 序列化与反序列化
- 优化被重写的
clone()
方法,在方法中将浅克隆的对象属性进行克隆
小结
单例模式:保证全局唯一
工厂模式:生产一个产品(一般使用简单工厂模式)
抽象工厂模式:生产一个产品族
建造者模式:让创建与调用分离,便于创建复杂对象(前提对象结构差异性不大)
原型模式:当对象复杂时,更高效的创建一个对象(克隆原有的对象)