java开发之设计模式

1.设计模式分类
创建型模式
工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
结构型模式
适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式
行为型模式
策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
2.设计模式原则
1).开闭原则(Open Close Principle)
开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。
为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,需要使用接口和抽象类
2).里氏代换原则(Liskov Substitution Principle)
里氏代换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。
里氏代换原则中任何基类可以出现的地方,子类一定可以出现。
LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为。
里氏代换原则是对“开-闭”原则的补充。实现“开-闭”原则的关键步骤就是抽象化。
而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
3).依赖倒转原则(Dependence Inversion Principle)
这个是开闭原则的基础,具体内容:真对接口编程,依赖于抽象而不依赖于具体。
4).迪米特法则(最少知道原则)(Demeter Principle)
一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
5).接口隔离原则(Interface Segregation Principle)
使用多个隔离的接口,比使用单个接口要好。还是一个降低类之间的耦合度
6).合成复用原则(Composite Reuse Principle)
原则是尽量使用合成/聚合的方式,而不是使用继承。
3.单例设计模式
保证一个类只有一个实例,并且提供一个访问该全局访问点
4.单例应用场景
servlet
struts
spring
springMVC
连接池
线程池
5.单例的优点
1)在单例模式中,活动的单例只有一个实例,对单例类的所有实例化得到的都是相同的一个实例。
这样就防止其它对象对自己的实例化,确保所有的对象都访问一个实例
2)单例模式具有一定的伸缩性,类自己来控制实例化进程,类就在改变实例化进程上有相应的伸缩性。
3)提供了对唯一实例的受控访问。
4)由于在系统内存中只存在一个对象,因此可以节约系统资源,当需要频繁创建和销毁的对象时单例模式无疑可以提高系统的性能。
5)允许可变数目的实例
6)避免对共享资源的多重占用。
6.单例缺点
1)不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。
2)由于单利模式中没有抽象层,因此单例类的扩展有很大的困难
3)单例类的职责过重,在一定程度上违背了“单一职责原则
4)滥用单例将带来一些负面问题,如为了节省资源将数据库连接池对象设计为的单例类,可能会导致共享连接池对象的程序过多而出现连接池溢出
如果实例化的对象长时间不被利用,系统会认为是垃圾而被回收,这将导致对象状态的丢失。
7.单例创建方式
1).饿汉式
类初始化时,会立即加载该对象,线程天生安全,调用效率高。

public class HungrySingleton {
	//类初始化时,创建对象,线程安全,会浪费内存
	public static HungrySingleton h=new HungrySingleton();
	private HungrySingleton() {
		System.out.println("类已初始化");
	}
	
	public static HungrySingleton getInstance() {
		return h;
		
	}
	public static void main(String[] args) {
		HungrySingleton hungry1 = h.getInstance();
		HungrySingleton hungry2 = h.getInstance();
		System.out.println(hungry1==hungry2);
		
	}
		
}
2).懒汉式
		类初始化时,不会初始化该对象,真正需要使用的时候才会创建该对象,具备懒加载功能。非线程安全
public class LazySingleton {
	//类初始化时不会创建对象
	private static LazySingleton l=null;
	private LazySingleton() {
		System.out.println("类已初始化");
	}
	
	public synchronized static LazySingleton getInstance() {
		if(l==null) {
			l=new LazySingleton();
		}
		return l;
	}
	public static void main(String[] args) {
		LazySingleton lazySingleton1 = l.getInstance();
		LazySingleton lazySingleton2 = l.getInstance();
		System.out.println(lazySingleton1==lazySingleton2);
	}
	
}
	3).静态内部方式
		结合了懒汉式和饿汉式各自的优点,真正需要对象的时候才会加载,加载类是线程安全的。
public class StaticSingleton {
	
	private  StaticSingleton() {
		System.out.println("对象已初始化...");
	}
	
	private static class Singleton{
		public static final StaticSingleton s=new StaticSingleton();
	}
	public static StaticSingleton getInstance() {
		return Singleton.s;
		
	}
	public static void main(String[] args) {
		StaticSingleton staticSingleton1 = StaticSingleton.getInstance();
		StaticSingleton staticSingleton2 = StaticSingleton.getInstance();
		System.out.println(staticSingleton1==staticSingleton2);
	}
	
}
	4).枚举单例
		使用枚举实现单例模式
		优点是:实现简单、调用效率高,枚举本身就是单例,由jvm从根本上提供保障,避免通过反射和反序列化的漏洞
		缺点是:没有延迟加载
public class EnumSingleton {
	private EnumSingleton() {
		System.out.println("类已初始化");
	}
	public static EnumSingleton getInstance() {
		return EnumSingletons.INSTANCE.getInstance();
		
	}
	static enum EnumSingletons {
		INSTANCE;
		
		public EnumSingleton singleton;
		
		private EnumSingletons() {
			singleton=new EnumSingleton();
		}
		
		public EnumSingleton getInstance() {
			return this.singleton;
			
		}
		
	}
	public static void main(String[] args) {
		EnumSingleton singleton1 = EnumSingleton.getInstance();
		EnumSingleton singleton2 = EnumSingleton.getInstance();
		System.out.println(singleton1==singleton2);
	}
}
	5).双重检测锁方式
		因为JVM本质重排序的原因,可能会初始化多次,不推荐使用
public class LinkedCheckLockSingleton {
	private static LinkedCheckLockSingleton l=null;
	private LinkedCheckLockSingleton() {
		System.out.println("类已初始化");
	}
	public static LinkedCheckLockSingleton getInstance() {
		if(l==null) {
			synchronized (LinkedCheckLockSingleton.class) {
				if(l==null) {
					l=new LinkedCheckLockSingleton();
				}
			}
		}
		return l;
		
	}
	public static void main(String[] args) {
		LinkedCheckLockSingleton checkLockSingleton1 = LinkedCheckLockSingleton.getInstance();
		LinkedCheckLockSingleton checkLockSingleton2 = LinkedCheckLockSingleton.getInstance();
		System.out.println(checkLockSingleton1==checkLockSingleton2);
	}
}

8.什么是枚举?
	枚举本身是单例的,一般用于项目中定义常量
9.内部类会在什么时候初始化对象?
	需要外部类调用内部类才会初始化对象
10.工厂设计模式
	 实现了创建者和调用者分离
11.工厂设计模式好处
	是用工厂方法代替new操作的一种模式。
	利用工厂模式可以降低程序的耦合性,为后期的维护修改提供了很大的便利。
	将选择实现类、创建对象统一管理和控制。从而将调用者跟我们的实现类解耦。
12.工厂设计模式分类
	1).简单工厂模式
		简单工厂模式相当于是一个工厂中有各种产品,创建在一个类中,客户无需知道具体产品的名称,只需要知道产品类所对应的参数即可。
		但是工厂的职责过重,而且当类型过多时不利于系统的扩展维护
	2).工厂方法模式
		工厂方法模式Factory Method,又称多态性工厂模式。
		在工厂方法模式中,核心的工厂类不再负责所有的产品的创建,而是将具体创建的工作交给子类去做。
		该核心类成为一个抽象工厂角色,仅负责给出具体工厂子类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
	3).抽象工厂模式
		抽象工厂简单地说是工厂的工厂,抽象工厂可以创建具体工厂,由具体工厂来产生具体产品。
13.简单工厂与工厂方法、抽象工厂区别
	1).简单工厂
		用来生产同一等级结构中的任意产品,不支持拓展增加商品
	2).工厂方法
		用来生产同一等级结构中的固定产品,支持拓展增加商品
	3).抽象工厂
		用来生产不同产品族的全部产品,不支持增加拓展商品,支持增加产品族
14.代理设计模式
	通过代理控制对象的访问,可以详细访问某个对象的方法,在方法之前处理或者在方法之后处理,即AOP微实现,AOP核心技术是面向切面编程。
15.代理设计模式应用场景
	SpringAOP
	事务原理
	日志打印
	权限控制
	远程调用
	安全代理
16.代理分类
	静态代理
		静态定义代理类
	动态代理
		动态生成代理类
17.静态代理
	由程序员创建或工具生成代理类的源码,再编译代理类。
	所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
18.动态代理
	1.代理对象,不需要实现接口
	2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
	3.动态代理也叫做:JDK代理,接口代理
19.JDK动态代理
	1)原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生成代理,位于java.lang.reflect包下)
	2).实现方式:
		1. 通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);    ----()
		2. 通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类Class clazz = Proxy.getProxyClass(classLoader,new Class);
		3. 通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型Constructor constructor = clazz.getConstructor()
		4. 通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入Interface Proxy = (Interface)constructor.newInstance();
		5.无
20.JDK动态代理的缺点
	jdk动态代理,必须是面向接口,目标业务类必须实现接口
21.CGLIB动态代理
	原理:利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
22.CGLIB动态代理与JDK动态区别
	JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
	而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
	JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。
	CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。
	因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态
23.建造者模式
	建造者模式是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
24.建造者应用场景
	1)需要生成的对象具有复杂的内部结构
	2)需要生成的对象内部属性本身相互依赖
25.建造者模式和工厂模式区别
	建造者模式:建造者模式更加关注与零件装配的顺序
	工厂模式:实现目标与调用者分离
26.	建造者模式包含角色
	1).Builder
		给出一个抽象接口,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。
	2).ConcreteBuilde
		实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。 在建造过程完成后,提供产品的实例。
	3).Director
		调用具体建造者来创建复杂对象的各个部分,在指导者中不涉及具体产品的信息,只负责保证对象各部分完整创建或按某种顺序创建。
	4)Product
		要创建的复杂对象
27.模板方法模式
	不同的代码全部存放在父类中,不同的业务,使用抽象方法,抽取给子类进行实现
	抽取过程---抽象方法。
28.模板方法应用场景
	数据库访问的封装
	Junit单元测试
	servlet中关于doGet/doPost方法的调用
	Hibernate中模板程序
	spring中JDBCTemplate
	HibernateTemplate
29.什么时候使用模板方法
	实现一些操作时,整体步骤很固定,但是其中一小部分容易变,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现
30.适配器模式
	在设计模式中,适配器模式(英语:adapter pattern)有时候也称包装样式或者包装(wrapper)。
	将一个类的接口转接成用户所期待的。
	一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中
31.适配器分类
	适配器分为:类适配器、对象适配、接口适配方式
	类适配器方式采用继承方式,对象适配方式使用构造函数传递
32.适配器应用场景
	1)使用第三方的类库,或者说第三方的API的时候,通过适配器转换来满足现有系统的使用需求。
	2)旧系统与新系统进行集成的时候,我们发现旧系统的数据无法满足新系统的需求,可能需要适配器,完成调用需求
	3)使用不同数据库之间进行数据同步。(这里只是分析的是通过程序来说实现的时候的情况。还有其他的很多种方式[数据库同步])
33.外观模式
	外观模式(Facade Pattern)门面模式,隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。
	这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性
	这种模式涉及到一个单一的类,该类提供了客户端请求的简化方法和对现有系统类方法的委托调用。
34.原型模式
	原型模式是一种创建型模式,原型表明了该模式有一个样板实例,用户从这个样板对象中复制一个内部属性一致对象,这个过程称为"克隆"
	被复制的实例称为"原型",这个原型是可定制的,原型模式多用于创建复杂或者构造耗时的实例,因为这种情况下复制一个已经存在的实例可使实例运行更高效
35.原型模式应用场景
	1)类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等,通过原型拷贝避免消耗
	2)通过new产生的一个对象需要非常繁琐的数据准备或者权限,这时可以使用原型模式
	3)一个对象需要提供给其他对象访问,而各个调用者可能需要修改值时,可以考虑使用原型模式拷贝多个对象供调用者使用,即保护性拷贝
36.VO、DTO 、DO、PO的概念区别和用处
	1).VO(view Object)
		视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来
	2).DTO(data transfer Object)
		数据传输对象,这个概念来源于J2EE设计模式,原来的目的是为了把EJB的分布式应用提供细粒度的数据实体,以减少分布式调度次数
		从而提高分布式调用的性能和降低网络负载,在原型模式中是指用于展示与服务之间的数据传输对象
	3).DO(Domain Object)
		领域对象,从现实世界中抽象出来的有形或者无形业务实体
	4).PO(persistent Object)
		持久化对象,它跟持久层的数据结构形成一一对应的映射关系,如果持久层是关系型数据库
		那么数据中的每个字段(或若干个)就对应PO的一个或者若干个属性
37.原型模式深复制和浅复制
	1).深复制
		在计算机中开辟了一块新的内存地址用于存放复制的对象
	2).浅复制
		只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,这种拷贝称为"浅复制"
		浅复制仅仅是指向被复制的内存地址,如果原地址对象改变了,那么浅复制出来的对象也会相应改变
38.装饰者模式
	装饰器模式,也成为包装模式,是对已经存在的某些类进行装饰,以此来扩展一些功能
39.装饰与代理区别
	装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。
	用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。
	因此,当使用代理模式的时候,常常在一个代理类中创建一个对象的实例。
	并且,当我们使用装饰器模式的时候,通常的做法是将原始对象作为一个参数传给装饰者的构造器。
40.装饰者模式应用场景
	在IO中,具体构件角色是节点流,装饰角色是过滤流
41.策略模式
	定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化
42.策略模式应用场景
	策略模式的用意是针对一组算法或逻辑,将每一个算法或逻辑封装到具有共同接口的独立的类中,从而使得它们之间可以相互替换
	策略模式使得算法或逻辑可以在不影响到客户端的情况下发生变化,策略模式属开闭原则,即对拓展开放,对修改关闭
	策略模式的出现诠释了开闭原则,有效的减少了分支语句
43.观察者模式
	观察者模式(observer)是一种行为型模型,行为型模型关注的是系统中对象之间的相互交互,解决系统在运行时对象之间的相互通信和协作
	进一步明确对象的职责,和创建型模式相比,创建型模式关注对象的创建过程,结构型模式关注对象和类的组合关系
44.观察者职责
	观察者模式主要用于1对N的通知,当一个对象的状态变化时,需要即使告知一系列对象,令它们作出响应
45.观察者实现方式
	推:每次都会把通知以广播形式发送给所有观察者,所有观察者只能被动接收
	拉:观察者只需要知道情况即可,至于什么时候获取内容,获取什么内容都可以自主决定
46.观察者应用场景
	关联行为场景,需要注意的是,关联行为是可分的,而不是"组合"关系
	事件多级触发场景
	跨系统的消息交换场景,如消息队列,事件总线的处理机制
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值