8. 设计模式

本文详细介绍了Java设计模式中的单例模式(懒汉式、饿汉式及线程安全解决方案)、工厂模式、静态工厂方法模式和装饰器模式。单例模式用于确保类只有一个实例,常用于配置文件读取、线程池和数据库连接池。工厂模式则提供了一种创建对象的接口,延迟到子类确定实例化哪个类。静态工厂方法模式简化了对象创建过程,而装饰器模式则通过组合扩展对象功能。设计模式的应用提高了代码可读性、可扩展性和重用性。
摘要由CSDN通过智能技术生成

设计模式基础知识点

一、单例模式

单例模式的概念

所谓的单例模式指的是一个类中允许产生一个实例化对象

  1. 单例只能有一个实例

  2. 单例类必须自己创建自己的唯一实例

  3. 单例类必须给所有其他对象提供这一实例

最好理解的一种设计模式,分为懒汉式和饿汉式

举例说明:一个系统共享一个对象:Person类

public class Person {
 
private int id;	
public Person(int id){
	this.id = id;
}
public Person() {
	super();
}

public void test(){
	Singleton sing = Singleton.getInstance();
	System.out.println(sing.hashCode());
}
}

单例模式中的懒汉式

public class Singleton {
 
//私有化构造
private Singleton(){
	System.out.println("对象创建成功");
}

//全局对象
private static Singleton singleton = null;	

//调用getInstance方法才会创建对象
public static synchronized Singleton getInstance(){
	//判断全局对象是否为空
	if(singleton == null){
		//如果为空,就创建该对象
		singleton = new Singleton();
	}
	//如果不为空,返回该对象
	return singleton;
}

public static void main(String[] args) {		
	//多线程操作
	//2.直接使用Thread操作
	Thread thread1 = new Thread(){
		@Override
		public void run() {
			// TODO Auto-generated method stub
			//
			Singleton sin = Singleton.getInstance();
			System.out.println(sin.hashCode());
		}
	};
	//开启新线程
	thread1.start();
	
	Thread thread2 = new Thread(){
		@Override
		public void run() {
			// TODO Auto-generated method stub
			Singleton sin2 = Singleton.getInstance();
			System.out.println(sin2.hashCode());
		}
	};		
	
	thread2.start();
		
	Person person  = new Person();
	person.test();
	
	Singleton sin3 = new Singleton();
	System.out.println(sin3.hashCode());//与上不同

单例模式中的饿汉式:

public class Singleton2 {
 
//跟懒汉式的区别:直接创建对象
private static Singleton2 ton = new Singleton2();

//私有构造
private Singleton2(){
	System.out.println("对象创建成功");
}

public static Singleton2 getInstance(){
	return ton;		
}

public static void main(String[] args) {
	// TODO Auto-generated method stub
 
	Singleton2 ton = Singleton2.getInstance();
	System.out.println(ton.hashCode());
}
}

单例模式中的线程安全问题以及解决方案

懒汉式解决线程安全问题
public class Singleton3 {
private Singleton3() {
	System.out.println("对象创建成功");
}

//全局对象
private static Singleton3 singleton=null;

public static Singleton3 getInstance() {
	//判断全局对象是否为空
	if(singleton==null) {
		//休眠一秒钟
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//线程锁
		synchronized (Singleton3.class) {
			if(singleton==null) {
				//如果为空,就创建该类对象
				singleton=new Singleton3();
			}
		}
	}
	//如果不为空,就直接返回该对象
	return singleton;
}

public static void main(String[] args) {
	//多线程操作
	//2.直接使用Thread操作
	Thread thread1=new Thread(){
		@Override
		public void run() {
			// TODO Auto-generated method stub
			//
			Singleton3 ton=Singleton3.getInstance();
			System.out.println(ton.hashCode());
		}
	};
	thread1.start();
	Thread thread2=new Thread(){
		@Override
		public void run() {
			// TODO Auto-generated method stub
			Singleton3 ton2=Singleton3.getInstance();
			System.out.println(ton2.hashCode());
		}
	};
	//开启新线程
	thread2.start();
}
}

线程安全

饿汉式本身是线程安全的,可以直接用于多线程而不会出现问题

懒汉式是非线程安全的,解决方式如下:

关键字: synchronized: 可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码

	//调用getInstance方法才会创建对象
public static synchronized Singleton getInstance(){
	//判断全局对象是否为空
	if(singleton == null){
		//如果为空,就创建该对象
		singleton = new Singleton();
	}
	//如果不为空,返回该对象  缺点: 效率低下
	return singleton;
}
实现单例的几种方法
  1. 所谓单例就是在系统中只有一个该类的实例

  2. 单例模式的核心分为以下三个步骤:

    1. 构造方法私有化. 即不能在类为实例化, 只能在类内实例化

    2. 在本类中创建本类的实例

    3. 在本类中提供给外部获取实例的方式

  3. java 中单例模式的实现方式有两种:

  4. 饿汉模式: 不管现在需要不需要, 先创建实例, 关键在于”饿”,饿了就要立刻吃

懒汉模式: 需要时再创建, 关键在于”懒”,类似懒加载

二、工厂设计模式(工厂模式分为工厂方法模式和抽象工厂模式)

意图:

定义一个创建对象的接口, 让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行

主要解决: 主要解决接口选择的问题

何时使用: 我们明确地计划不同条件下创建不同实例时

如何解决: 让其子类实现工厂接口,返回的也是一个抽象的产品

关键代码: 创建过程在其子类执行

三、静态工厂方法模式

将多个工厂方法模式里的方法置为静态的,不需要创建实例,直接调用即可.

四、建造者模式

工厂类模式提供的是创建单个类的模式, 而建造者模式则是将各种产品集中起来管理,用于创建复合对象,所谓复合对象就是指某个类具有不同的属性

五、适配器设计模式

适配器模式是将某个类的接口转换成客户端期望的另一个接口表示, 目的是消除由于接口不匹配所造成的类的兼容性问题.

主要分为三类:

类的适配器模式,对象的适配器模式,接口的适配器模式.

六、装饰模式

意图:

装饰者模式通过组合的方式扩展对象的特征, 这种方式允许我们在任何时候对对象的功能进行扩展甚至是运动时扩展.

主要解决: 一般的,我们为了扩展一个类经常使用继承方式实现.由于继承为类引入静态特征,并且随着扩展功能的增加,子类会很膨胀.

如何使用: 在不想增加很多子类的情况下扩展类.

如何解决: 将具体功能职责划分, 同时继承装饰者模式.

.装饰模式 就是给一个对象增加 一些新的功能, 而且是动态的,要求装饰对象和被装饰对象实现 同一个接口,装饰对象持有 被装饰对象的实例.

装饰者模式具体详见链接:http://www.runoob.com/design-pattern/decorator-pattern.html

七、代理模式

代理模式指给一个对象提供一个代理对象,并由代理对象 控制对 原对象的引用. 代理可以分为 静态代理和 动态代理. 通过代理模式, 可以利用代理对象为 被代理对象 添加额外的功能,以此来扩展被代理对象的功能. 可以用于计算某个方法执行时间,在某个方法执行前后有记录日志等操作.

为什么使用设计模式

1、设计模式是前人根据经验总结出来的,使用设计模式,就相当于是站在了前人的肩膀上。

2、设计模式使程序易读。熟悉设计模式的人应该能够很容易读懂运用设计模式编写的程序。

3、设计模式能使编写的程序具有良好的可扩展性,满足系统设计的开闭原则。比如策略模式,就是将不同的算法封装在子类中,在需要添加新的算法时,只需添加新的子类,实现规定的接口,即可在不改变现有系统源码的情况下加入新的系统行为。

4、设计模式能降低系统中类与类之间的耦合度。比如工厂模式,使依赖类只需知道被依赖类所实现的接口或继承的抽象类,使依赖类与被依赖类之间的耦合度降低。

5、设计模式能提高代码的重用度。比如适配器模式,就能将系统中已经存在的符合新需求的功能代码兼容新的需求提出的接口 。

6、设计模式能为常见的一些问题提供现成的解决方案。

7、设计模式增加了重用代码的方式。比如装饰器模式,在不使用继承的前提下重用系统中已存在的代码。

单例模式的使用的场景

懒汉式单例、饿汉式单例、静态内部类单例、枚举和双重校验锁单例

  1. 由于配置文件一般都是共享资源,即web应用的配置对象的读取,一般采用单例模式来实现。如:spring的配置文件的读取等
  2. 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。
  3. 数据库连接池的设计也是采用单例模式的。数据库连接其实也是一种数据连接的共享资源,在jdbc连接中如果在做频繁操作的时候,不停的打开或者关闭会效能损耗,因此用单例模式来维护就大大降低了这种效能损耗。
  4. 网站计数器,一般是采用单例模式实现,否则难以同步。
  5. 应用程序的日志应用,一般都何时用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
  6. 在Spring中创建的Bean实例默认都是单例模式存在的。

单例模式应用的场景一般有两个条件:

​ 1、资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的应用配置、数据连接池的设计。

2、控制资源的情况下,方便资源之间的互相通信。

如多线程的线程池设计等。https://www.iteye.com/blog/qinzy212-126-com-2217184

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值