共有23种设计模式,可分为三大类:创建型模式,结构型模式以及行为型模式
创建型模式: 该设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式, 而不是使用new直接实例化对象, 这使得程序在判断针对某个给定实例需要创建哪些对象时更为灵活。 | 1.工厂模式 2.抽象工厂模式 3.单例模式 4.建造者模式 5.原型模式 |
结构型模式 这些设计模式关注类和对象的组合,继承的概念被用来组合接口和定义组合对象获得新 功能的方式 | 1.适配器模式 2.桥接模式 3.过滤器模式 4.组合模式 5.装饰器模式 6.外观模式 7.享元模式 8.代理模式 |
行为型模式 这些设计模式特别关注对象之间的通信 | 1.责任链模式 2.命令模式 3.解释器模式 4.迭代器模式 5.观察者模式 6.状态模式 7.策略模式 8.访问者模式 |
工厂模式:
这是java最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一中创建对象的最佳方式。在工厂模式中,我们再创建对象时不会对客户端暴露逻辑,并且是通过使用一个公共的接口来指向新创建的对象。
意图:定义一个创建对象的接口,让其子类自己去决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决:主要解决接口选择问题。
何时使用:明确地计划不同条件下创建不同实例时。
关键代码:创建过程在其子类执行
优点:1.一个调用者想创建一个对象,只需要知道其名称就行。2.扩展性高,如果想增加一个产品,只需要扩展一个工厂类就行。3.屏蔽产品的具体实现,调用者只关心产品的接口。
缺点:每次增加一个产品,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加。增加了复杂度。
单例模式
是java中最简单的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这个模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建,这个类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
1.单例类只能有一个实例(对象)
2.单例类必须自己创建自己的唯一实例
3.单例类必须给其他对象提供这一实例,也就是让其他用户能够访问到该实例(instance函数)。
意图:保证一个类只有一个实例,并提供一个访问它的全局访问点(instance)
主要解决:一个全局使用的类频繁地创建与销毁。
何时使用:当你想控制实例数目,节省系统资源的时候
如何解决:判断系统是否已经有这个单例,若有则返回,没有则创建。
关键代码:构造函数是私有的。
优点:1.在内存中只有一个实例,减少了内存的开销。
缺点:没有借口,不能继承。
建造者模式
使用多个简单的对象一步步构造成一个复杂的对象,这种类型的设计模式属于创建型模式,提供了一种创建对象的最佳方式。
一个builder类会一步步构造最终的对象,该builder类是独立于其他对象的。
意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。
主要解决:一个复杂对象的创建工作,其通常由各个部分的子对象用一定算法构成,由于需求的变化,这个复杂对象的各个部门经常面临剧烈的变化。
关键代码:建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系。
优点:1.建造者独立,易拓展。2.便于控制细节风险。
缺点:1.产品必须有共同点,范围有限制。2.如果内部变化复杂,会有很多建造类。
原型模式
用于创建重复的对象,同时又能保证性能。
实现了一个原型接口,该接口用于创建当前对象的克隆,当直接创建对象的代价比较大时,则采用这种模式。
意图:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
主要解决:在运行期建立和删除原型。
如何解决:利用已有的一个原型对象,快速生成和原型对象一样的实例。
优点:1.性能提高。2.逃避构造函数的约束
缺点:1.必须实现cloneable接口。
适配器模式(继承或依赖)
作为两个不兼容的接口之间的桥梁,这种类型的设计模式属于结构型模式,结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。
意图:将一个类的接口转换成客户希望的另外一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的哪些类能够一起工作。
主要解决:在软件系统中,常常要将一些现存的对象放在新的环境中,而新环境要求的接口是现对象不能满足的。
何时使用:1.系统需要使用现有的类,而此类的接口不符合系统的需要。
如何解决:继承或依赖
关键代码:适配器继承或依赖已有的对象,实现想要的目标接口。
优点:1.可以让任何两个没有关联的类一起运行。2.提高了类的复用。3.增加了类的透明度。4.灵活性好
缺点:1.过多的使用适配器,会让系统非常凌乱。2.由于java至多继承一个类,所以至多只能适配一个适配者类。而且目标类必须是抽象类。
装饰器模式
装饰者模式允许向一个现有的对象添加新的功能,同时又不改变其结构,是作为现有类的一个包装。
意图:动态地给一个对象添加一些额外的职责(功能)
主要解决:一般为了拓展一个类经常使用继承方式实现,但这种方式会随着拓展功能的增多,子类会很膨胀。
何时使用:在不想增加很多子类的情况下扩展类。
关键代码:1.component类充当抽象角色,不应具体实现(抽象类)。2.修饰类引用和继承component类。具体拓展类重写父类方法。
优点:装饰类和被装饰类可以独立发展,不会互相耦合。
缺点:多层装饰比较复杂。