深入解析设计模式:分类、创建与结构模式详解

深入解析设计模式:分类、创建与结构模式详解

一.设计模式 1.简介

设计模式是经过分类编目的代码设计经验。

设计模式的基本要素;设计模式的分类,其一,模式依据其目的可进行划分;其二,范围准则是分类的一个方面。

指定模式主要是用于类还是用于对象。

3.创建模式

创建模式指的是对类的实例化过程进行抽象化。

一些系统在创建对象时,需要去动态地确定创建对象的方式以及创建哪些对象。创建模式对怎样构造和封装这些动态的决定进行了描述。

4.结构模式

结构模式描述如何把类或者对象组合在一起以形成更大的结构,这种结构模式描述了两类不同的事物,一类是类,另一类是类的实例。

5、行为模式

在不同对象之间划分责任与算法,同时解决对象之间的相互作用方式

2.工厂模式 1)定义

工厂模式在 Java 中较为常用。它属于创建型模式。这种模式能提供创建对象的最佳方式。

工厂模式又叫静态工厂方法模式、简单工厂

2)结构

工厂类是模式的核心。此类包含着必要的判断逻辑,能够决定在何种情况下创建某一个产品类的实例。客户端无需直接承担创建产品对象的责任,只需负责“消费”产品。简单工厂模式凭借这种方式实现了对责任的划分。

创建测试接口及实现类,

3)创建工厂

通过中间的工厂调用其他类的方法

3.单例(Singleton)模式 1)定义

单例模式能保证某一个类仅有一个实例存在。它会自行进行实例化操作,并且将这个实例提供给整个系统。

这里有三个要点:

某个类仅能有一个实例,类必须自己去创建这个实例,并且以公共、统一的方式将这个实例提供给整个系统。 应用。

很多时候整个系统只需拥有一个全局对象,这有利于我们对系统整体的行为进行协调。

在某个服务器程序里,该服务器的配置信息被存放在一个文件当中。这些配置数据是由一个单例对象来进行统一读取的。接着,服务进程中的其他对象会通过这个单例对象去获取这些配置信息。

这种方式简化了在复杂环境下的配置管理

借助编程语言自身所具有的语法特性,对某个类进行强制限制,使其不能创建出多个实例。

3)分类 1.饿汉式EngerSingLeton

直接创建对象

public class EagerSingleton {
    private static final EagerSingleton m_instance = new EagerSingleton();
​
    private EagerSingleton() {
    }
​
    public static EagerSingleton getInstance() {
        return m_instance;
    }
}

2.懒汉式LazySingLeton

先判断在创建对象

public class LazySingleton {
    private static LazySingleton m_instance = null;
​
    private LazySingleton() {
    }
​
    public static LazySingleton getInstance() {
        if (m_instance == null) {
            m_instance = new LazySingleton();
        }
        return m_instance;
    }
}

4.Prototype模式

原型模式就是 Prototype 模式。原型模式是一个较为单纯的设计模式。它的目的是借助一个原型对象,能够迅速地生成一批对象,以此避免重复进行新建的过程。

工作原理是,把一个原型对象传递给一个将要新建的对象,新建对象会请求原型对象进行拷贝,接着它自己来进行创建。

1)适应场景

主要适用于以下情况:

2)结构 … 二.代理模式 1.简介

大家对“代理”这个词并不陌生。我们都知晓代理商。简单来讲,代理商就是替厂家售卖商品。厂家会委托代理来为其销售商品,而顾客则会找代理购买商品。

使用代理通常有两个优点,并且这两个优点能够分别与我们提到的代理商的几个特点相对应。

关于代理商,其一,我们从他们处购买东西时,往往不清楚背后的厂家具体是谁,这意味着委托者对于我们而言是不可见的;其二,代理能够对顾客进行定位,从而更精准地售卖给有需求的客户群体。

代理模式是 Java 设计模式中常用的一种。其特征在于,代理类与委托类具备相同的接口。代理类主要承担以下任务:为委托类预处理消息;对消息进行过滤;把消息转发给委托类;以及在事后对消息进行处理等。

代理类和委托类通常存在关联关系。一个代理类的对象会与一个委托类的对象相关联。代理类的对象自身并不实际去实现服务。它是通过调用委托类的对象的相关方法,从而来提供特定的服务。

代理模式的作用是为其他对象提供一种代理,从而控制对该对象的访问。它创建一个代理对象,让这个代理对象充当客户端与目标对象之间的中介。其主要目的在于保护目标对象或者增强目标对象。

通过使用代理模式,通常有以下两个优点:

隐藏被代理类的实现能够实现客户与被代理类间的解耦,并且在不修改被代理类代码的情况下还能够做一些额外的处理。

按照代理的创建时期,代理类可以分为两种。

3)Proxy模式结构

由三部分组成:

2.静态代理

如果代理类在程序运行之前就已经存在了,那么这种代理方式就叫做静态代理。在这种情况下,代理类通常是我们在 Java 代码中定义出来的。

所谓的静态代理,是通过声明一个明确的代理类去访问源对象。一个代理仅能服务于一种产品。当存在 n 种产品时,就需要 n 个代理。这样的情况不利于业务的发展。

我们拥有两个接口,分别是 Computer 和 Phone,并且每个接口都对应着一个实现类。

定义接口,也就是代理接口;定义实现类,即委托类;定义代理类 Proxy,这个代理类最终还是会调用委托类来实现业务操作。

通过代理类调用的方法调用实现类的方法

1)优缺点

静态代理的代码较为简单且容易理解。这种模式有着自身的优势,然而,它也存在着较为明显的不足之处:

3.动态代理

代理类在程序运行期间创建的代理方式被称作动态代理。即在此情况下,代理类并非在 Java 代码中预先定义好的,而是在运行过程中依据我们在 Java 代码里的指示而动态生成的,在程序运行时,通过运用反射机制来动态创建出代理对象。

JDK从1.3版本就开始支持动态代理类的创建。

java.lang.reflect 类库中提供了三个类,它们直接对代理模式提供支持,分别是 Proxy、InvocationHandler 和 Method

1)JDK原生动态代理

Java 原生对其提供支持,无需外部依赖。不过,它仅能基于接口来进行代理,这意味着需要动态代理的对象必须要实现某个接口。

Proxy类

Proxy 具备创建动态代理类和实例的功能,它拥有用于此的静态方法。同时,它还是由这些静态方法所创建的所有动态代理类的上一级类别。

核心方法 newProxyInstance 能够返回一个具有指定接口的代理类实例,这个实例可以把方法调用指派给指定的调用处理程序。

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
 //参数说明:
定义代理类的类加载器为 loader;代理类要实现的接口列表是 interfaces;指派方法调用的调用处理程序是 h。
类加载器在 Proxy 类的 newProxyInstance()方法中需要一个 ClassLoader 类的实例,而这个 ClassLoader 实际上对应的就是类加载器。

InvocationHandler类

代理实例的调用处理程序 实现的接口

每个代码实例都有一个与之相关联的调用处理程序。当对代理实例调用方法时,会对该方法调用进行编码,并将其指派给其调用处理程序的 invoke 方法。

package java.lang.reflect;
public interface InvocationHandler { 
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}
//参数说明:
//Object proxy:在其上调用方法的代理实例。
//Method method:要调用的方法
//Object\[] args:方法调用时所需要的参数
可以把 InvocationHandler 接口的子类当作一个代理的最终操作类,然后将 ProxySubject 替换掉。

public class JDKProxy implements InvocationHandler {
    private final Object target;
    public JDKProxy(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        long start = System.currentTimeMillis();
        Object obj = method.invoke(target, args);
        long end = System.currentTimeMillis();
        System.out.println(method.getName() + "耗时" + (end - start) + "ms");
        return obj;
    }

Method类

Method 会提供关于类或接口上某个单独方法的信息,同时也会告知如何访问该方法。所反映出的方法可以是类方法,也可以是实例方法,其中还包括抽象方法。

主要方法是 invoke:调用带有指定参数的指定对象所对应的由该 Method 对象所表示的基础方法。

public Object invoke(Object obj,
                     Object... args)
参数包括 obj,这是从中调用基础方法的对象;还有 args,是用于方法调用的参数。

2)CGLIB动态代理

[CGLIB] CGLIB

CGLIB 以继承的方式来实现代理,使得需要代理的类成为 Enhancer 的父类。它不依赖于目标对象是否实现了接口,都能够进行代理。然而,它无法处理 Final 的情况,这需要依赖外包来解决。

public class CGLibProxy {
    public static Object getProxy(final Object target) {
        //创建enhancer对象
        Enhancer enhancer = new Enhancer();
        //创建代理对象为超级类
        enhancer.setSuperclass(target.getClass());
        //调用应用
        enhancer.setCallback(new MethodInterceptor() {
            /**
             * @author Arran
             * @description  
@params 包含 o、method、objects 和 methodProxy 。
             * @return java.lang.Object 
             * @date  2024/06/27 下午 03:13
             */
            
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("售前咨询 之前被调用");
                Object result = method.invoke(target, objects);
                System.out.println("售后处理 之后被调用");
                return result;
            }
        });
        //创建代理对象
        return enhancer.create();
    }
}

4.JDK代理与CGLIB代理的区别

​

通过调用方法 method,将参数 objects 传递给目标对象 target,从而得到对象结果 object result。
System 显示了“售后处理之后被调用”;
            return result;
        }
    });
    //创建代理对象
    return enhancer.create();
}


## 4.JDK代理与CGLIB代理的区别
- JDK动态代理实现接口,CGLIB动态继承思想
JDK 动态代理在目标对象存在接口的情况下,其执行效率比 CIGLIB 要高。
如果对象具备接口实现,那么就选择 JDK 代理;倘若对象没有接口实现,就选择 CGILB 代。
​     

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

25阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读