浅谈源码的七大设计模式

本文会介绍一些经典的设计模式思想:

常用设计模式

Proxy代理模式

代理模式:为其他对象提供一种代理以便控制对这个对象的访问。

可以详细控制访问某个类(对象)的方法,在调用这个方法前作的前置处理(统一的流程代码放到代理中处理)。调用这个方法后做后置处理。

代理模式分类:

1.静态代理(静态定义代理类,我们自己静态定义的代理类。比如我们自己定义一个明星的经纪人类)

2.动态代理(通过程序动态生成代理类,该代理类不是我们自己定义的。而是由程序自动生成)比较重要!!

  • JDK自带的动态代理
  • javaassist字节码操作库实现
  • CGLIB
  • ASM(底层使用指令,可维护性较差)

结构组成

代理模式主要涉及到三个角色:抽象角色、代理角色、真实角色(被代理的角色)。

抽象角色:声明真实对象和代理对象的共同接口。即真实对象和代理对象共同要实现的行为动作(好比房东和中介都要能够实现租房的行为,都能把房子租给你)。

代理角色:代理角色内部含有对真实角色的引用,从而可以去操作真实对象,同时代理对象提供与真实对象的接口,以便在任何时候都能代替真实对象。同时,代理对象在执行真实对象的操作时,也能附加它自己的操作,相当于对真实对象的封装

真实角色:代理角色所代理的对象,亦即我们最终要引用的对象。

Factory工厂模式

工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。

工厂模式可以分为三类:

  • 简单工厂模式(Simple Factory)
  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)

这三种模式从上到下逐步抽象,并且更具一般性。GOF在《设计模式》一书中将工厂模式分为两类:工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)。将简单工厂模式(Simple Factory)看为工厂方法模式的一种特例,两者归为一类。

区别:

工厂方法模式:

  • 一个抽象产品类,可以派生出多个具体产品类。
  • 一个抽象工厂类,可以派生出多个具体工厂类。

每个具体工厂类只能创建一个具体产品类的实例。

抽象工厂模式:

  • 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。
  • 一个抽象工厂类,可以派生出多个具体工厂类。
  • 每个具体工厂类可以创建多个具体产品类的实例。

区别:

工厂方法模式只有一个抽象产品类,而抽象工厂模式有多个。

工厂方法模式的具体工厂类只能创建一个具体产品类的实例,而抽象工厂模式可以创建多个。

Singleton单例模式

  • 单例模式只能有一个实例。
  • 单例类必须创建自己的唯一实例。
  • 单例类必须向其他对象提供这一实例。

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式结构图

单例模式(Singleton)是几个创建模式中最对立的一个,它的主要特点不是根据用户程序调用生成一个新的实例,而是控制某个类型的实例唯一性,通过上图我们知道它包含的角色只有一个,就是Singleton,它拥有一个私有构造函数,这确保用户无法通过new直接实例它。除此之外,该模式中包含一个静态私有成员变量instance与静态公有方法Instance()。Instance()方法负责检验并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。

使用Singleton模式有一个必要条件:在一个系统要求一个类只有一个实例时才应当使用单例模式。反之,如果一个类可以有几个实例共存,就不要使用单例模式。

不要使用单例模式存取全局变量。这违背了单例模式的用意,最好放到对应类的静态成员中。

不要将数据库连接做成单例,因为一个系统可能会与数据库有多个连接,并且在有连接池的情况下,应当尽可能及时释放连接。Singleton模式由于使用静态成员存储类实例,所以可能会造成资源无法及时释放,带来问题。

Delegate委派模式

委派模式(Delegate)是面向对象设计模式中常用的一种模式。这种模式的原理为类B和类A是两个互相没有任何关系的类,B具有和A一模一样的方法和属性;并且调用B中的方法,属性就是调用A中同名的方法和属性。B好像就是一个受A授权委托的中介。第三方的代码不需要知道A的存在,也不需要和A发生直接的联系,通过B就可以直接使用A的功能,这样既能够使用到A的各种公能,又能够很好的将A保护起来了。

委派模式的优点:

  • 单一一个类无法表现复杂的设计
  • 设计拆分
  • 方便重用
  • 相对独立
  • 功能定义清晰,行为界面分离
  • 松散耦合,容易扩展

strategy策略模式

定义一系列的算法,把每一个算法封装起来, 并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。也称为政策模式(Policy)。(Definea family of algorithms,encapsulate each one, andmake them interchangeable. Strategy lets the algorithmvary independently from clients that use it. )

策略模式把对象本身和运算规则区分开来,其功能非常强大,因为这个设计模式本身的核心思想就是面向对象编程的多形性的思想。

策略模式结构

当存在以下情况时使用Strategy模式

? 许多相关的类仅仅是行为有异。 “策略”提供了一种用多个行为中的一个行为来配置一个类的方法。即一个系统需要动态地在几种算法中选择一种。

? 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 /时间权衡的算法。当这些变体实现为一个算法的类层次时 ,可以使用策略模式。

? 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。

? 一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

Prototype原型模式

原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对象的副本,这种创建对象的方式,相比我们之前说的几类创建型模式还是有区别的,之前的讲述的工厂模式与抽象工厂都是通过工厂封装具体的new操作的过程,返回一个新的对象,有的时候我们通过这样的创建工厂创建对象不值得,特别是以下的几个场景的时候,可能使用原型模式更简单也效率更高。

? 当一个系统应该独立于它的产品创建、构成和表示时,要使用 Prototype模式

? 当要实例化的类是在运行时刻指定时,例如,通过动态装载;

? 为了避免创建一个与产品类层次平行的工厂类层次时

? 当一个类的实例只能有几个不同状态组合中的一种时。建立相应数目的原型并克隆它们可能比每次用合适的状态手工实例化该类更方便一些。(也就是当我们在处理一些对象比较简单,并且对象之间的区别很小,可能只是很固定的几个属性不同的时候,可能我们使用原型模式更合适)。

原型模式结构

Template模板模式

  • 模板方法模式是一种类的行为型模式,在它的结构图中只有类之间的继承关系,没有对象关联关系。
  • 板方法模式是基于继承的代码复用基本技术,模板方法模式的结构和用法也是面向对象设计的核心之一。在模板方法模式中,可以将相同的代码放在父类中,而将不同的方法实现放在不同的子类中。
  • 在模板方法模式中,我们需要准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来让子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现,这就是模板方法模式的用意。模板方法模式体现了面向对象的诸多重要思想,是一种使用频率较高的模式。

模板方法应用于下列情况:

  • 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
  • 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
  • 控制子类扩展。模板方法只在特定点调用“ hook”操作 ,这样就只允许在这些点进行扩展。

模板模式结构

参考文档:https://mp.weixin.qq.com/s/IAf0avCHoptHspOi71UxnA

原文地址:https://www.cnblogs.com/itbuyixiaogong/p/9060193.html

时间: 2025-01-13 16:34:51

浅谈源码的七大设计模式的相关文章

访何红辉:谈谈Android源码中的设计模式

最近Android 6.0版本的源代码开放下载,刚好分析Android源码的技术书籍<Android源码设计模式解析与实战>上市,我们邀请到它的作者何红辉,来谈谈Android源码中的设计模式,以及近期Android开发中的一些热点话题. 受访嘉宾介绍: 何红辉(@MrSimp1e),前友盟Android工程师,活跃于国内各大技术社区,热爱开源,热爱技术,热爱分享.Android开源库 AndroidEventBus . Colorful 作者, 开发技术前线 站长,<Android源码

JDK 源码 阅读 - 2 - 设计模式 - 创建型模式

A.创建型模式 抽象工厂(Abstract Factory) javax.xml.parsers.DocumentBuilderFactory DocumentBuilderFactory通过FactoryFinder实例化具体的Factory. 使用例子: DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilder

《Prism 5.0源码走读》 设计模式

Prism或Prism构建的应用程序时会使用大量的设计模式,本文简要列举Prism相关的那些设计模式. Adapter(适配器模式):Prism Library主要在Region和IoC container应用Adapter模式. ContentControlRegionAdapter.cs ItemsControlRegionAdapter.cs SelectorRegionAdapter.cs UnityServiceLocatorAdapter.cs MefServiceLocatorAd

Android 源码中的设计模式

最近看了一些android的源码,发现设计模式无处不在啊!感觉有点乱,于是决定要把设计模式好好梳理一下,于是有了这篇文章. 面向对象的六大原则 单一职责原则 所谓职责是指类变化的原因.如果一个类有多于一个的动机被改变,那么这个类就具有多于一个的职责.而单一职责原则就是指一个类或者模块应该有且只有一个改变的原因.通俗的说,即一个类只负责一项职责,将一组相关性很高的函数.数据封装到一个类中. 开闭原则 对于扩展是开放的,这意味着模块的行为是可以扩展的.当应用的需求改变时,我们可以对模块进行扩展,使其

从源码中学习设计模式系列——单例模式序/反序列化以及反射攻击的问题(二)

一.前言 这篇文章是学习单例模式的第二篇,之前的文章一下子就给出来看起来很高大上的实现方法,但是这种模式还是存在漏洞的,具体有什么问题,大家可以停顿一会儿,思考一下.好了,不卖关子了,下面我们来看看每种单例模式存在的问题以及解决办法. 二.每种Singleton 模式的演进 模式一 public class LazySingleton { private static LazySingleton lazySingleton = null; private LazySingleton() { }

再谈源码阅读

在软件开发中遇到问题的时候,我倾向于在不需要阅读源码的情况下解决问题,我会优先去查官方文档.FAQ.google或stackoverflow等网站,去看下有没有前人已经遇到过同类问题.阅读源码来解决问题,算是杀手锏.当然,还有另一种需求,就是希望通过阅读源码了解软件的设计细节,来达到学习的目的,例如,通过阅读Dubbo的源码,我可以了解一个RPC框架的设计细节. 前提 阅读源码之前要做一定的准备工作. 首先,确保自己掌握了相关的基础知识,例如,如果你要阅读Linux内核源码,要掌握C语言的语法.

8.源码分析---从设计模式中看SOFARPC中的EventBus?

我们在前面分析客户端引用的时候会看到如下这段代码: // 产生开始调用事件 if (EventBus.isEnable(ClientStartInvokeEvent.class)) { EventBus.post(new ClientStartInvokeEvent(request)); } 这里用EventBus调用了一下post方法之后就什么也没做了,就方法名来看是发送了一个post请求,也不知道发给谁,到底有什么用. 所以这一节我们来分析一下EventBus这个类的作用. 首先我们来看一下

浅谈ASCII码、unicode编码、UTF-8编码的区别

字符集:是一堆字符组成的集合,用来指定字节或者字符串映射成二进制的规则 (在计算机中存储的,无论是字节还是字符串都是以二进制模式存储的.) ASCII编码和Unicode编码的区别: ASCII编码是1个字节,而Unicode编码通常是2个字节(2-4个字节). 字母A用ASCII编码是十进制的65,二进制的01000001: 字符0用ASCII编码是十进制的48,二进制的00110000,注意字符'0'和整数0是不同的: 汉字"中"已经超出了ASCII编码的范围,用Unicode编码

spring源码学习之设计模式(1)单例模式

众所周知,单例模式分为饿汉式和懒汉式,昨天在看了<spring5核心原理与30个类手写实战>之后才知道饿汉式有很多种写法,分别适用于不同场景,避免反射,线程不安全问题.下面就各种场景.采用的方式及其优缺点介绍. 饿汉式 (绝对的线程安全) 代码示例 1.第一种写法 ( 定义即初始化) public class Singleton{ private static final Singleton instance = new Singleton(); private Singleton() {}