概述
设计模式代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员针对某一类问题的最优解决方案,是从许多优秀的软件系统中总结出来的。
使用设计模式的目的:为了提高代码的可重用性、让代码更容易被他人理解、保证代码可靠性,让代码编写更加工程化。
Java中设计模式通常有23种。
1.大致可分为3类:创建型、行为型和结构型。
设计模式的六大原则
2.开闭原则
开闭原则的意思是:对扩展开放,对修改关闭。在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。简言之,是为了使程序的扩展性好,易于维护和升级。想要达到这样的效果,我们需要使用接口和抽象类
3.里氏转换原则
里氏代换原则是面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。里氏代换原则是对开闭原则的补充。实现开闭原则的关键步骤就是抽象化,而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。
依赖倒转原则
这个原则是开闭原则的基础,具体内容:针对接口编程,依赖于抽象而不依赖于具体
4. 接口隔离原则
这个原则的意思是:使用多个隔离的接口,比使用单个接口要好。它还有另外一个意思是:降低类之间的耦合度。由此可见,其实设计模式就是从大型软件架构出发、便于升级和维护的软件设计思想,它强调降低依赖,降低耦合。
5.迪米特法则,又称最少知道原则
最少知道原则是指:一个实体应当尽量少地与其他实体之间发生相互作用,使得系统功能模块相对独立。
6. 合成复用原则
合成复用原则是指:尽量使用合成/聚合的方式,而不是使用继承。
创建型模式
创建型模式设计对象的实例化,特点是不让用户代码依赖于对象的创建或排列方式,避免用户直接用new创建对象。
创建型模式有5种。
工厂模式、抽象工厂模式、建造者模式、原型模式和单列模式
工厂模式
工厂模式是java中最常见的设计模式之一,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
目的:定义一个创建对象的接口,让子类自己去决定实例化那个产品类,也就是子类去实现接口
注意事项:
作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
抽象工厂模式
抽象工厂模式(Abstract
Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
意图:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
两种设计模式主要的区别在于产品,工厂模式是用来创建同一个产品的不同类型的,而抽象工厂模式是用来创建不同类的产品。一般来说,产品种类单一,适合用工厂模式;如果有多个;多种类型时,通过抽象工厂模式来创建时很合适的。
单例模式
单例模式是Java最简单的设计模式,这种设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种设计模式涉及到一个单一的类,该类负责创建自己的对象同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
单例类只能有一个实例。
单例类必须自己创建自己的唯一实例
单例类必须给所有其他对象提供这一实例关键代码:构造函数是私有的。
建造者模式
建造者模式使用多个简单的对象一步步构建成复杂的对象。这种类型的设计模式属于创建型设计模式,它提供了一种创建对象的最佳方式。
一个Builder类会一步一步构造最终的对象。该Builder类是独立于其他对象的。
原型模式
原型模式是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种设计模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。
意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
关键代码:实现cloneable接口,重写clone()方法。当通过new产生一个对象需要非常繁琐的数据准备或访问权限,或者类初始化消耗非常多的资源,这个资源包括数据、硬件资源时。可以使用原型模式
装饰者模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。
主要解决:一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
举例
装饰模式:以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案;代理模式:给一个对象提供一个代理对象,并有代理对象来控制对原有对象的引用;
装饰模式应该为所装饰的对象增强功能;代理模式对代理的对象施加控制,并不提供对象本身的增强功能
装饰者模式的定义:动态的将责任附加到被装饰者对象上,用于扩展对象的功能。比继承的灵活性大。典型的如Java IO的设计即是装饰者模式的典型应用。 代理模式模式的定义:对其他对象进行代理,以控制对被代理对象的访问。Spring的为业务逻辑层方法生成的代理类,主要进行一些事务控制等。由定义可以看出装饰的责任是扩展功能 ,而代理主要控制访问。
动态代理技术:动态代理技术就是用来产生一个对象的代理对象。
代理对象的价值:
1.代理对象存在的价值主要用于拦截对真实业务对象的访问。2.代理对象应该具有和目标对象(真实业务对象)相同的方法。
Java中的代理:java.lang.reflect.Proxy类
要生成某一个对象的代理对象,这个代理对象通常也要编写一个类来生成,java在JDK1.5之后提供了一个"java.lang.reflect.Proxy"类,通过"Proxy"类提供的一个newProxyInstance方法用来创建一个对象的代理对象。
newProxyInstance方法用来返回一个代理对象,这个方法总共有3个参数,ClassLoader loader用来指明生成代理对象使用哪个类装载器,Class>[]
interfaces用来指明生成哪个对象的代理对象,通过接口指定,InvocationHandler h用来指明产生的这个代理对象要做什么事情
注意:在java中规定,要想产生一个对象的代理对象,那么这个对象必须要有一个接口