常用的设计模式---------创建型模式

1、设计模式的种类

  • 创建型模式:
    单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式
  • 结构型模式:
    适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式,代理模式
  • 行为型模式:
    模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、接解释器模式、状态模式、策略模式、职责链模式、访问者模式。

2、OOP七大法则

  • 开闭原则:对扩展开放,对修改关闭。
  • 里氏替换原则:继承必须确保超类所拥有的性质在子类中仍然成立。
  • 依赖倒置原则:要面向接口编程,不要面向实现编程。
  • 单一职责原则:控制类的粒度大小、将对象解耦、提高其内聚性。
  • 接口隔离原则:要为各个类建立他们需要专用接口。
  • 迪米特法则:只与你的朋友直接交谈,不跟陌生人说话。
  • 合成复用原则:尽量先使用组合或者聚合等关联关系来实现,其次才考虑使用继承关系来实现。
  • 注:在项目中改动别人的代码是大忌

3、单例模式

单例模式便是创建型设计模式的一种,它确保某一个类在系统中只有一个实例,并自行实例化,同时向外部提供获取这个唯一实例的接口。

  • 设计思想:
  1. 避免因创建多个实例而导致的调用错误,单例模式保证使整个项目访问的是同一个实例
  2. 减少内存开销
  • 单例模式的三大特性:
  1. 单例类只有一个实例。
  2. 单例类必须自己实例化自己。
  3. 单例类需要向外提供实例。
  • 解决思路:
  1. 其他程序不能new该对象
  2. 在该类中创建本类对象属性
  3. 对外提供统一的获取对象方法
  • 目的
  1. 私有化构造函数------------------------------------------不能被实例化
  2. 在本类中创建一个本类对象的属性-----------------------创建统一的调用属性
  3. 定义一个公有的方法,返回创建的本类对象-------------提供统一的对象入口
  • 访问方式:
    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、简单工厂模式

用来生产同一等级结构中的任意产品(对于增加新的产品,需要覆盖已有代码)

  • 特点
  1. 有一个重要的create()方法,利用if或者 switch创建产品并返回。
  2. create()方法通常是静态的,所以也称之为静态工厂。
  • 缺点
  1. 扩展性差(静态方法不能被继承和重写,我想增加一种产品,除了新增一个产品类,还需要修改工厂类方法)
  2. 不同的产品需要不同额外参数的时候 不支持。
  3. 违背“开闭原则” 在这里插入图片描述

4.2、工厂方法模式

多方法的工厂模式为不同产品,提供不同的生产方法,使用时 需要哪种产品就调用该种产品的方法,使用方便、容错率高。

  • 使用步骤:
    步骤1: 创建抽象工厂接口,定义具体工厂的公共接口;
    步骤2: 创建抽象产品接口 ,定义具体产品的公共接口;
    步骤3: 创建具体产品类(继承抽象产品接口), 定义生产的具体产品;
    步骤4:创建具体工厂类(继承抽象工厂接口),定义创建对应具体产品实例的方法;
    步骤5:外界通过调用具体工厂类的方法,从而创建不同具体产品类的实例
  • 优点
    1. 更符合开-闭原则
    2. 符合单一职责原则
    3. 不使用静态工厂方法,可以形成基于继承的等级结构。
      在这里插入图片描述

结构复杂度:简单工厂优
代码复杂度:简单工厂优
编程复杂度:简单工厂优
管理复杂度:简单工厂优
设计原则上:工厂方法优
实际业务上:简单工厂多
注:并不是所有设计都要满足设计原则,因为会导致系统过于复杂,具体情况具体分析

4、抽象工厂模式(超级工厂创建产品系列工厂)

  • 定义:抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,无需指定它们具体的类。
  • 使用场景:
    1. 客户端不依赖于产品类实例如何被创建,实现等细节
    2. 强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码
    3. 提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现
  • 优点:
    1. 具体产品在应用层的代码隔离,无需关系创建的细节
    2. 将一个系列的产品统一到一起创建
  • 缺点:
    1. 规定了所有可能被创建的产品集合,不易于扩展产品簇。
    2. 增加了系统的抽象性和理解难度
      在这里插入图片描述

在这里插入图片描述

5、建造者模式

  • 定义:将一个复杂下的构建于他的表示分离,使得同样的构建过程可以创建不同的表示
  • 主要作用:咋用户不知道 对象的建造过程的细节 的情况下就可以直接创建复杂的对象
  • 用户只需要给出指定的对象类型和内容,建造者模式负责按顺序创建复杂对象(把内部额建造过程和细节隐藏起来)
    在这里插入图片描述
    角色分析:

指挥者:控制调用的先后顺序

  1. 监视者模式:有指挥者角色,负责指挥工人执行工人按照顺序建造;(规定工人执行方法的顺序)
  2. 匿名模式:无指挥者角色,由调用者(消费者)选择(可采用链式编程改变产品属性值和工人执行顺序)

工人(抽象的):工人能做的事情(抽象方法)
工人实现:工人执行方法的具体实现
产品: 最后被创建的对象

  • 优点:
    1. 产品的建造和表示分离,实现了解耦,使用建造者模式,可以使客户端不必知道产品内部组成的细节。
    2. 将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰。
    3. 具体的建造者类之间是相互独立的,这有利于系统的扩展。增加新的具体建造者无需修改原有类库的代码,符合”开闭原则
  • 缺点:
    1. 建造者模式所创建的产品一般具有较多的共同点(属性或方法),组成部分相似。如果产品间差异性很大,则不适合使用建造者模式。因此其使用范围受到一定的限制。
    2. 如果产品内部的变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统庞大。

建造者与抽象工厂模式的比较

  1. 返回内容不同:
    1. 建造者模式:返回一个完整的产品
    2. 抽象工厂模式:返回一系列相关的产品,这些产品构成一个产品族
  2. 获取产品方式:
    1. 建造者模式:可以不直接调用建造者模式,可以通过静态代理指挥者,有指挥者控制产品对象的生成(方法实现内容及顺序),返回一个完整产品。
    2. 抽象工厂模式:需要实例化工厂,调用工厂方法获取所需产品对象。

6、原型模式

  • 克隆
  • Prototype //原型
  • Cloneable接口
  • clone() 方法 (调用本地的C++方法)

6.1、浅克隆(浅拷贝)

实现流程:

  1. 被克隆对象实现Cloneable接口,重写clone() 方法
  2. 实例化后的克隆对象调用clone() 方法(返回值是Object对象需要强转)

特点:
3. 克隆对象与被克隆对象 内存中指向同一数据(共享数据源,拷贝了引用地址)
4. hash值不同

6.2、深克隆(深拷贝)

实现方案:

  1. 序列化与反序列化
  2. 优化被重写的 clone() 方法,在方法中将浅克隆的对象属性进行克隆

小结

单例模式:保证全局唯一
工厂模式:生产一个产品(一般使用简单工厂模式)
抽象工厂模式:生产一个产品族
建造者模式:让创建与调用分离,便于创建复杂对象(前提对象结构差异性不大)
原型模式:当对象复杂时,更高效的创建一个对象(克隆原有的对象)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值