java设计模式

1、设计模式的七大原则

(1)开闭原则:我们在设计软件系统时,考虑到后续功能的扩展和维护,需要使得设计的系统对扩展开放,对修改关闭,也就是在不修改原有软件的基础上可以轻松实现功能的扩展。
(2)接口隔离原则:我们在设计一个接口的时候,如果发现接口中的方法要么被同时使用,要么就同时不被使用,就需要考虑使用子接口去拆分这些接口,采用多个隔离的子接口去取代一个统一的接口,这样可以降低类与类之间的耦合度。
(3)单一职责原则:即一个类应该只负责一个功能职责,如果一个类A中有两种不同的职责,当一个职责需求改变的时候,可能会引起另外的职责的功能出错,因此需要将这个类进行细粒度的划分,拆解为两个类分别管理职责。
(4)依赖倒转:依赖倒转的核心思想就是面向接口编程,具体就是抽象的结构不应该依赖具体的细节,而是具体的细节依赖抽象,比如,我们在一个类中需要定义一个接口A的实现类的对象,可以定位为:A a = new A_implement();因为抽象的东西相比于细节的东西更稳定,以抽象为基础搭建的系统会比基于细节搭建的系统更加稳健。
(5)里氏替换原则:里氏替换原则说明,继承实际上会让两个类之间的耦合度增强,在适当的情况下使用聚合、组合、依赖等来解决问题。
(6)迪米特法则:迪米特法则又叫最少知道原则,也就是一个类A依赖于另外一个类B,那么类A对于类B的具体的实现细节应该知道的越少越好,不管被依赖的类有多复杂,都将逻辑封装在自己的类内部,不要对外暴露。

2、java中的设计模式总共有23种,可以分为三种类型。

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

3、代理模式有哪些?

代理模式分为静态代理和动态代理,动态代理又可以分为JDK代理和CGLIB代理。
(1)静态代理
静态代理中,代理类和被代理类需要实现相同的接口,并去重写里面的方法。在静态代理中,代理类需要在内部维护一个被代理类的对象,实现对这个被代理类的管理。
代理类实现:

//代理对象,静态代理
public class TeacherDaoProxy implements ITeacherDao{
	
	private ITeacherDao target; // 目标对象,通过接口来聚合	
	//构造器
	public TeacherDaoProxy(ITeacherDao target) {
		this.target = target;  //在代理类构造器中对被代理类对象进行初始化操作
	}
	@Override
	public void teach() {  //代理类和被代理类实现了相同的接口,则重写相同的方法
		// TODO Auto-generated method stub
		System.out.println("开始代理  完成某些操作。。。。。 ");//方法
		target.teach();
		System.out.println("提交。。。。。");//方法
	}
}

被代理类实现:

public class TeacherDao implements ITeacherDao {

	@Override
	public void teach() {
		// TODO Auto-generated method stub
		System.out.println(" 老师授课中  。。。。。");
	}

}

(2)jdk代理
jdk代理和静态代理一样,都是基于接口实现进行代理的,只不过jdk动态代理不像静态代理一样,要求我们自己写一个实际的代理类并去实现一个确定的接口(因为每一个类都去写一个代理类的话会造成类泛滥),而是通过编写一个代理工厂(ProxyFactory)去根据你的需求返回一个定制的代理类对象,体现出动态性,也就是需要通过反射机制实现动态代理,在jdk代理中有两个关键的类/接口,Proxy类和InvocationHandler接口。
代理工厂实现:

public class ProxyFactory {

	private Object target;  //这个是我们需要维护的一个被代理类对象,不管是什么代理方法,都是需要维护一个被代理对象的
	
	public ProxyFactory(Object target){
		this.target = target;   //在代理工厂构造器中对这个被代理类对象进行初始化
	}
	
	//用于获取代理对象的方法
	public Object getProxyInstance(){
		MyInvocationHandler handler = new MyInvocationHandler();   //这个就是关键的Invocationhandler接口的实现
		handler.band(target);
		//通过Proxy类中的newProxyInstance方法生成代理对象proxyInstance,该方法需要传入一个类加载器、被代理类所实现的接口以及一个处理器handler
		Object proxyInstance = Proxy.newProxyInstance(target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(),handler);
		return proxyInstance;
	}
	//这个handler类需要我们自己去编写并实现InvocationHandler接口
	class MyInvocationHandler implements InvocationHandler{
		private Object object;  //同样,这个handler对象也需要持有对应的被代理类对象
		public void band(Object obj){
			object = obj;   //这个方法用于设置被代理类
		}
		//重写接口中的invoke方法
		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			// TODO 自动生成的方法存根
			System.out.println("JDK动态代理开始");
			Object returnVal = method.invoke(target, args);  //这里的target是被代理类对象
			System.out.println("后续处理");
			return returnVal;
		}	
	}
}

(3)cglib代理
cglib代理和jdk代理一样,都是动态代理方式,只不过cglib代理不要求被代理对象一定要实现某个接口,底层都是依靠反射机制完成对代理对象的创建并返回的。cglib代理依赖于两个重要的类/接口,一个是Enhancer类和MethodIntercepter接口。
代理工厂实现:

public class ProxyFactory implements MethodInterceptor {
	
	//维护一个被代理的对象
	private Object target;	
	public ProxyFactory(Object target){
		this.target = target;
	}

	//如果想要使用cglib动态代理,就需要让生成代理对象的工厂实现方法拦截器,并且充写里面的intercepter方法
	@Override
	public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
		// TODO 自动生成的方法存根
		System.out.println("cglib动态代理开始。。。");
		Object returnVal = method.invoke(target, args);
		System.out.println("cglib动态代理结束");
		return returnVal;
	}
	
	public Object getProxyInstance(){
		//生成一个工具类对象
		Enhancer enhancer = new Enhancer();
		//使用工具类对象设置父类
		enhancer.setSuperclass(target.getClass());
		
		//使用工具设置回调函数
		enhancer.setCallback(this);
		
		//使用工具类对象创建代理对象
		return enhancer.create();
		
	}
}

4、单例模式
单例模式指的是在程序运行期间,始终只存在唯一一个当前类型的对象。单例模式的实现分为懒汉式和饿汉式两种方式,并且单例模式的类的构造器是private私有化的,也就是不允许在外部构造新的对象,对象的构造只允许在类的内部进行,并对外暴露一个静态的公有方法,返回在类内部创建的单例对象。
(1)饿汉式
饿汉式指的是在类的字节码文件进行加载的时候就创建一个对象,以后在需要使用到这个对象的时候,只需要调用静态的公有方法就可以返回这个对象。饿汉式属于线程安全的实现 方式,因为整个对象的创建过程只在类加载时进行,而jvm在进行类加载时,自动就是线程安全的。饿汉式的实现方式有两种:静态变量和静态代码块
静态变量实现:

//饿汉式(静态变量)

class Singleton {
	
	//1. 构造器私有化, 外部能new
	private Singleton() {	
	}
	//2.本类内部创建对象实例
	private final static Singleton instance = new Singleton();
	
	//3. 提供一个公有的静态方法,返回实例对象
	public static Singleton getInstance() {
		return instance;
	}
}

静态代码块实现:

class Singleton {
	
	//1. 构造器私有化, 外部不能new
	private Singleton() {
		
	}
	//2.本类内部创建对象实例
	private  static Singleton instance;
	
	static { // 在静态代码块中,创建单例对象
		instance = new Singleton();
	}
	
	//3. 提供一个公有的静态方法,返回实例对象
	public static Singleton getInstance() {
		return instance;
	}
}

(2)懒汉式
懒汉式指的是在类加载的时候并不进行对象的创建,而是在需要用到这个单例对象的时候才去创建,因此在多线程的条件下,懒汉式需要解决多线程带来的问题,因为多个线程操作,可能造成这个单例模式设计的类并不是单例类。懒汉式实现线程安全的方式有:同步方法、双重检查
同步方法实现:

// 懒汉式(线程安全,同步方法)
class Singleton {
	private static Singleton instance;
	
	private Singleton() {}
	
	//提供一个静态的公有方法,加入同步处理的代码,解决线程安全问题,但是将同步的机制放在返回单例对象的方法上面,造成多线程条件下并发效率低下的问题
	//即懒汉式
	public static synchronized Singleton getInstance() {
		if(instance == null) {
			instance = new Singleton();
		}
		return instance;
	}
}

双重检查方式实现:

// 懒汉式(线程安全,双重检查)
class Singleton {
	private static volatile Singleton instance;
	
	private Singleton() {}
	
	//提供一个静态的公有方法,加入双重检查代码,解决线程安全问题, 同时解决懒加载问题
	//同时保证了效率, 推荐使用
	
	public static  Singleton getInstance() {
		//双重检查实现线程安全,并且保证懒加载和效率问题
		if(instance==null){   //在第一次进来时,如果线程A,B都进入这个if判断,看谁先拿到锁,如果线程A拿到锁的话,线程B等待
			//线程A进入同步代码块,判断当前instance是否等于null,此时等于null,完成instance的初始化,退出同步代码快并且返回instance,此时A
			//的getInstance动作完成,由于A释放了锁此时B也可以进入同步代码块,由于我们将instance这个变量设置为volatile修饰(这个
			//代表一旦变量被修改就马上保存到内存,即实时更新),所以B进入同步代码块中进行if判断的时候,发现这个instance不是null,就直接返回。
			//当后续还有线程来的时候,第一个if判断就进不了,直接返回对象。
			//这里使用Singleton.class这个Class对象充当锁的作用
			synchronized(Singleton.class){
				if(instance==null){
					instance = new Singleton();
				}
			}
		}
		return instance;
	}
}

静态内部类实现方式:

// 静态内部类完成, 推荐使用
class Singleton {
	private Singleton(){
		
	}
	
	/*
	 * 采用静态内部类的方式之所以能够实现单例,就是因为在静态内部类中已经被创建好了,没有后续的new对象的动作
	 * 并且实现了懒加载,因为jvm在加载外部类的时候,不会加载静态内部类,只有当调用getInstance的时候 。jvm才会
	 * 去加载静态内部类并且完成里面静态常量的初始化,但是是如何实现线程安全的呢?这是利用了jvm加载的线程安全特性,就是
	 * 在jvm加载的时候,属于线程安全的,所以里面的instance也只能被new一次。
	 * 
	 * */

	//定义一个静态内部类,里面包含一个静态的Singleton常量
	private static class SingletonInstance{
		private static final Singleton INSTANCE = new Singleton();
	}
	
	public static Singleton getInstance(){
		return SingletonInstance.INSTANCE;
	} 
}

枚举类实现方式:

//使用枚举,可以实现单例, 推荐
enum Singleton{
	INSTANCE;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1) 优秀的程序应该是这样的:阅读时,感觉很优雅;新增功能时,感觉很轻松;运行时,感觉很快速,这就需要设计模式支撑。2) 设计模式包含了大量的编程思想,讲授和真正掌握并不容易,网上的设计模式课程不少,大多讲解的比较晦涩,没有真实的应用场景和框架源码支撑,学习后,只知其形,不知其神。就会造成这样结果: 知道各种设计模式,但是不知道怎么使用到真实项目。本课程针对上述问题,有针对性的进行了升级 (1) 授课方式采用 图解+框架源码分析的方式,让课程生动有趣好理解 (2) 系统全面的讲解了设计模式,包括 设计模式七大原则、UML类图-类的六大关系、23种设计模式及其分类,比如 单例模式的8种实现方式、工厂模式的3种实现方式、适配器模式的3种实现、代理模式的3种方式、深拷贝等3) 如果你想写出规范、漂亮的程序,就花时间来学习下设计模式吧课程内容和目标本课程是使用Java来讲解设计模式,考虑到设计模式比较抽象,授课采用 图解+框架源码分析的方式1) 内容包括: 设计模式七大原则(单一职责、接口隔离、依赖倒转、里氏替换、开闭原则、迪米特法则、合成复用)、UML类图(类的依赖、泛化和实现、类的关联、聚合和组合) 23种设计模式包括:创建型模式:单例模式(8种实现)、抽象工厂模式、原型模式、建造者模式、工厂模式。结构型模式:适配器模式(3种实现)、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式(3种实现)。行为型模式:模版方法模式、命令模式、访问者模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式(Interpreter模式)、状态模式、策略模式、职责链模式(责任链模式)2) 学习目标:通过学习,学员能掌握主流设计模式,规范编程风格,提高优化程序结构和效率的能力。
Java设计模式是一套对代码设计经验的总结,被人们反复利用,并且很多人都熟知的代码设计方式。其中,单例模式是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这种模式有几个好处,比如可以节约系统资源,提高程序效率,以及提供一个全局访问点等。在实现单例模式时,可以采用饿汉式单例模式,即在类加载时创建一个对象,并通过私有构造器和静态方法来保证对象的唯一性。另外,工厂方法模式也是Java中常用的设计模式之一。在工厂方法模式中,可以定义一个工厂类,该类负责创建对象的实例,并将其封装在一个工厂方法中。通过这种方式,可以实现对象的创建与使用的分离,提高代码的灵活性和可维护性。总的来说,Java设计模式是一种用于解决特定问题的通用解决方案,可以提高代码的重用性、可读性和可扩展性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Java常用设计模式](https://blog.csdn.net/qq_33327680/article/details/123815614)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [JAVA中23种设计模式](https://blog.csdn.net/qw_0214/article/details/78878531)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值