博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA设计模式
阅读量:5925 次
发布时间:2019-06-19

本文共 6730 字,大约阅读时间需要 22 分钟。

hot3.png

#一、面向对象OOP 面向对象设计的任务是对面向对象分析的结果作进一步的规范化整理,以便能够被面向对象编程直接接受。

面向对象设计是一种软件设计方法,是一种工程化规范。
概括地说,面向对象设计就是“根据需求决定所需的类、类的操作,以及类之间关联的过程”。

面向对象设计的主要工作包括:

  • 确定需要的类;
  • 给每个类提供一组完整的操作;
  • 明确地使用继承来表现共同点。

主要原则:

  • 模块化,对象就是模块;把数据结构和操作这些数据的方法紧密地结合在一起所构成的模块。
  • 抽象,面向对象方法不仅支持过程抽象,而且支持数据抽象。
  • 信息隐藏,在面向对象方法中,信息隐藏通过对象的封装性来实现。
  • 低耦合,耦合主要指不同对象之间相互关联的紧密程度。低耦合使得系统中某一部分的变化对其他部分的影响降到最低程度。

#二、设计原则

  1. 单一职责原则 (Single Responsibility Principle, SRP) 一个类只负责一个功能领域中的相应职责;
  2. 开闭原则 (Open-Closed Principle, OCP) 软件实体应对扩展开放,而对修改关闭;
  3. 里氏代换原则 (Liskov Substitution Principle, LSP)所有引用基类对象的地方能够透明地使用其子类的对象;
  4. 依赖倒转原则 (Dependence Inversion Principle, DIP) 抽象不应该依赖于细节,细节应该依赖于 抽象;
  5. 接口隔离原则 (Interface Segregation Principle, ISP) 使用多个专门的接口,而不使用单一的总接 口 ;
  6. 合成复用原则 (Composite Reuse Principle, CRP) 尽量使用对象组合,而不是继承来达到复用的 目的;
  7. 迪米特法则 (Law of Demeter, LoD) 一个软件实体应当尽可能少地与其他实体发生相互作用。

#三、设计模式

##创建型模式 ###1. 简单工厂模式

定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式。

简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。简单工厂模式结构比较简单,其核心是工厂类的设计。

主要角色: Factory(工厂角色) - Product(抽象产品角色)- ConcreteProduct(具体产品角色) 输入图片说明

###2. 工厂方法模式

定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。工厂方法模式又简称为工厂模式(Factory Pattern),又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。

工厂方法模式提供一个抽象工厂接口来声明抽象工厂方法,而由其子类来具体实现工厂方法,创建具体的产品对象。

主要角色: Factory(抽象工厂) - ConcreteFactory(具体工厂) - Product(抽象产品) - ConcreteProduct(具体产品) 输入图片说明

###3. 抽象工厂模式

提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式。在抽象工厂模式中,每一个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品族。

主要角色:AbstractFactory(抽象工厂) - ConcreteFactory(具体工厂)- AbstractProduct(抽象产品)- ConcreteProduct(具体产品) 输入图片说明

###4. 单例模式

确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。

单例模式有三个要点:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。

主要角色:Singleton(单例):在单例类的内部实现只生成一个实例,同时它提供一个静态getInstance()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。

输入图片说明

  • 饿汉式
class EagerSingleton {    private static final EagerSingleton instance = new EagerSingleton();    private EagerSingleton() { }    public static EagerSingleton getInstance() {        return instance;    }}
  • 懒汉式
class LazySingleton {    private volatile static LazySingleton instance = null;    private LazySingleton() { }    public static LazySingleton getInstance() {        //第一重判断        if (instance == null) {            //锁定代码块            synchronized (LazySingleton.class) {                //第二重判断                if (instance == null) {                        instance = new LazySingleton(); //创建单例实例                }            }        }    return instance;    }}
  • Initialization Demand Holder (IoDH):在单例类中增加一个静态(static)内部类,在该内部类中创建单例对象,再将该单例对象通过getInstance()方法返回给外部使用。
class Singleton {    private Singleton() {    }    private static class HolderClass {        private final static Singleton instance = new Singleton();    }    public static Singleton getInstance() {        return HolderClass.instance;    }    public static void main(String args[]) {        Singleton s1, s2;        s1 = Singleton.getInstance();        s2 = Singleton.getInstance();        System.out.println(s1==s2);    }}

饿汉式单例类在类被加载时就将自己实例化,它的优点在于无须考虑多线程访问问题,可以确保实例的唯一性;从调用速度和反应时间角度来讲,由于单例对象一开始就得以创建,因此要优于懒汉式单例。但是无论系统在运行时是否需要使用该单例对象,由于在类加载时该对象就需要创建,因此从资源利用效率角度来,饿汉式单例不及懒汉式单例,而且在系统加载时由于需要创建饿汉式单例对象,加载时间可能会比较长。

懒汉式单例类在第一次使用时创建,无须一直占用系统资源,实现了延迟加载,但是必须处理好多个线程同时访问的问题,特别是当单例类作为资源控制器,在实例化时必然涉及资源初始化,而资源初始化很有可能耗费大量时间,这意味着出现多线程同时首次引用此类的机率变得较大,需要通过双重检查锁定等机制进行控制,这将导致系统性能受到一定影响。

饿汉式单例类不能实现延迟加载,不管将来用不用始终占据内存;懒汉式单例类线程安全控 制烦琐,而且性能受影响。通过使用IoDH,我们既可以实现延迟加载,又可以保证线程安全,不影响系统性能,不失为一种最好的Java语言单例模式实现方式(其缺点是与编程语言本身的特性相关,很多面向对象 语言不支持IoDH)。

###5. 原型模式

使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

工作机制:将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝自己来实现创建过程。由于在软件系统中我们经常会遇到需要创建多个相同或者相似对象的情况,因此原型模式在真实开发中的使用频率还是非常高的。原型模式是一种“另类”的创建型模式,创建克隆对象的工厂就是原型类自身,工厂方法由克隆方法来实现。

需要注意的是通过克隆方法所创建的对象是全新的对象,它们在内存中拥有新的地址,通常对克隆所产生的对象进行修改对原型对象不会造成任何影响,每一个克隆对象都是相互独立的。通过不同的方式修改可以得到一系列相似但不完全相同的对象。

主要角色: Prototype(抽象原型类) - ConcretePrototype(具体原型类) - Client(客户类)

克隆方法:浅克隆(ShallowClone)和深克隆(DeepClone)。在Java语言中,数据类型分为值类型(基本数据类型)和引用类型,值类型包括int、double、byte、boolean、char等简单数据类型,引用类型包括类、接口、数组等复杂类型。浅克隆和深克隆的主要区别在于是否支持引用类型的成员变量的复制。

  • 浅克隆(ShallowClone) (implements Cloneable) 当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制; 输入图片说明

  • 深克隆(DeepClone) (implements Serializable ) 除了对象本身被复制外,对象所包含的所有成员变量也将复制。

    输入图片说明

###6. 建造者模式

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一种对象创建型模式。

建造者模式一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

主要角色:Builder(抽象建造者) - ConcreteBuilder(具体建造者) - Product(产品角色) - Director(指挥者)

输入图片说明

##结构型模式 ###1. 适配器模式

将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。适配器模式既可以作为类结构型模式,也可以作为对象结构型模式。

将一个类的接口和另一个类的接口匹配起来,而无须修改原来的适配者接口和抽象目标类接口。

  • 对象适配器
    适配器与适配者之间是关联关系
    主要角色:
    Target(目标抽象类) :目标抽象类定义客户所需接口,可以是一个抽象类或接口,也可以是具体类。
    Adapter(适配器类):适配器可以调用另一个接口,作为一个转换器,对Adaptee和Target进行适配,适配器类是适配器模式的核心,在对象适配器中,它通过继承Target并关联一个Adaptee对象使二者产生联系。
    Adaptee(适配者类):适配者即被适配的角色,它定义了一个已经存在的接口,这个接口需要适配,适配者类一般是一个具体类,包含了客户希望使用的业务方法,在某些情况下可能没有适配者类的源代码。
    输入图片说明
  • 类适配器
    适配器与适配者之间是继承(或实现)关系
    适配器类实现了抽象目标类接口Target,并继承了适配者类,在适配器类的request()方法中调用所继承的适配者类的specificRequest()方法,实现了适配。
    输入图片说明

优点:

1)将目标类和适配者类解耦,通过引入一个适配器类来重用现有的适配者类,无须修改原有结构。
2)增加了类的透明性和复用性
3)灵活性和扩展性都非常好,通过使用配置文件,可以很方便地更换适配器,也可以在不修改原有代码的基础上增加新的适配器类,完全符合“开闭原则”。

  • 双向适配器
  • 缺省适配器

###2. 代理模式

给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

代理模式是一种对象结构型模式。在代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到中介的作用,它去掉客户不能看到的内容和服务或者增添客户需要的额外的新服务。

主要角色:

1)Subject(抽象主题角色):它声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。
2) Proxy(代理主题角色):它包含了对真实主题的引用,从而可以在任何时候操作真实主题对象;在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主题;代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。通常,在代理主题角色中,客户端在调用所引用的真实主题操作之前或之后还需要执行其他操作,而不仅仅是单纯调用真实主题对象中。 3) RealSubject(真实主题角色):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。 输入图片说明
优点:
1)能够协调调用者和被调用者,在一定程度上降低了系统的耦合度; 2)客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则,系统具有较好的灵活性和可扩展性。
缺点:
1)由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢,例如保护代理。
2)实现代理模式需要额外的工作,而且有些代理模式的实现过程较为复杂,例如远程代理。

###3. 桥接模式

将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式。

桥接模式用一种巧妙的方式处理多层继承存在的问题,用抽象关联取代了传统的多层继承,将类之间的静态继承关系转换为动态的对象组合关系,使得系统更加灵活,并易于扩展,同时有效控制了系统中类的个数。 输入图片说明

###4. 外观模式

为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

外观模式又称为门面模式,它是一种对象结构型模式。外观模式是迪米特法则的一种具体实现,通过引入一个新的外观角色可以降低原有系统的复杂度,同时降低客户类与子系统的耦合度。 输入图片说明

###5. 组合模式

组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part-Whole)模式,它是一种对象结构型模式。

###6. 装饰模式

动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。

在装饰模式中,为了让系统具有更好的灵活性和可扩展性,我们通常会定义一个抽象装饰类,而将具体的装饰类作为它的子类。

###7. 享元模式

运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。

##行为型模式

  1. 观察者模式
  2. 访问者模式
  3. 中介者模式
  4. 模版方法模式
  5. 策略模式
  6. 状态模式
  7. 备忘录模式
  8. 迭代器模式
  9. 解释器模式
  10. 命令模式
  11. 职责链模式

转载于:https://my.oschina.net/u/1446182/blog/784980

你可能感兴趣的文章
有1000瓶水,3个瓶子可以再换1瓶,一共可以喝多少瓶?
查看>>
Search in Rotated Sorted Array ||
查看>>
NUC_HomeWork1 -- POJ2067(最短路)
查看>>
卸载mysql
查看>>
二叉树的遍历
查看>>
The Distinguish of the share or static lib in MFC
查看>>
linux下内存释放问题
查看>>
让Java和JavaScript进行交互
查看>>
linux逻辑卷管理
查看>>
LINQ之路12:LINQ Operators之数据转换(Projecting)
查看>>
SQL Server:数据库角色
查看>>
分享8个超棒的基于HTML5和jQuery的开发教程
查看>>
JFreeChart开发_用JFreeChart增强JSP报表的用户体验
查看>>
SpringMVC+Swagger详细整合
查看>>
计算机视觉领域最全汇总(第2部分)
查看>>
[译] 所有你需要知道的关于完全理解 Node.js 事件循环及其度量
查看>>
(六十九)复合语句
查看>>
我的友情链接
查看>>
设计模式:装饰者
查看>>
Java Web中实现Servlet的方式
查看>>