【设计模式】单例、工厂、装饰器、代理、适配器

目录

  • 单例模式
  • 简单工厂模式
  • 工厂模式
  • 抽象工厂模式
  • 装饰器模式
  • 代理模式
  • 适配器模式

单例模式

定义:确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

代码实现

【设计模式】单例、工厂、装饰器、代理、适配器_第1张图片

1、如何确保一个类只有一个实例?
构造方法不能公开,不能对外界实例化,用private修饰。这个实例是当前类的类成员变量,用static修饰。

2、如何向整个系统提供这个实例?
使用方法向外界提供这个实例。

3、根据对象实例化时机可以分为懒汉式和饿汉式加载。
例在类加载时就被创建,因此线程安全。但是如果该实例在程序运行过程中没有被使用,会造成资源浪费。而懒汉式出现的并发安全问题请看下面。

4、为什么要加volatile和synchronized?
创建一个单例对象可以分为三步:分配内存,初始化对象,指向刚分配的地址。如果发生重排序,线程A执行了1和3,还没有执行2,线程B判断NULL就会直接返回还没初始化的实例了,volatile可以避免重排序。而synchronized可以避免线程并发时重复创建对象。

5、有什么是用单例模式实现的?
在Java中,数据库连接池通常使用单例模式来实现,保证整个应用程序共享同一个数据库连接池实例,提高数据库连接的复用性和性能。


简单工厂模式

定义:又称为静态工厂方法,可以根据参数的不同返回不同类的实例。简单工厂模式专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。

代码实现

【设计模式】单例、工厂、装饰器、代理、适配器_第2张图片

优点:实现了创建对象和使用对象的分离,用户不需要关注创建对象的细节。

缺点:不够灵活,新增一个产品就要修改简单工厂类的逻辑。

有什么是用简单工厂模式实现的?
GUI界面库中的组件工厂,在GUI界面开发中,常常使用组件工厂来创建不同类型的GUI组件,如按钮、文本框、标签等。


工厂模式

定义:定义一个用于创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。

详细说明:
工厂模式是简单工厂模式的升级版,满足了开闭原则(对扩展开放,对修改关闭),解决了简单工厂模式的灵活性差的缺点。工厂模式将创建对象的工作交给了工厂的子类(延迟创建对象),自己只提供需要子类实现的方法。这样,在需要新增的时候就可以不破坏原来的结构。

【设计模式】单例、工厂、装饰器、代理、适配器_第3张图片

Collection就是抽象工厂,LinkedList和ArrayList就是实现了这个接口的具体工厂,Iterator是抽象工厂里的抽象产品,两个实现类可以通过被具体产品继承,接着根据抽象产品来实现定制的产品。

具体代码

public class Factory {
    public static void main(String【】 args) {
        FactoryA factoryA=new FactoryA();
        factoryA.createProduct().print();
        FactoryB factoryB=new FactoryB();
        factoryB.createProduct().print();
    }
}interface AbstractFactory{
    public Product1 createProduct();
}

class FactoryA implements AbstractFactory{
    @Override
    public Product1 createProduct(){
        return new ProductA();
    }
}
class FactoryB implements AbstractFactory{
    @Override
    public  Product1 createProduct(){
        return new ProductB();
    }
}

abstract class Product1 {
    public abstract void print();
}
class ProductA extends Product1 {
    @Override
    public void print(){
        System.out.println("ProductA正在打印!");
    }
}
class ProductB extends Product1 {
    @Override
    public void print(){
        System.out.println("ProductB正在打印!");
    }
}

IOC和工厂模式有什么不同?

1. 目的不同:IoC的目的是解耦组件之间的依赖关系,将对象的创建和管理交给容器来处理,使得代码更加灵活、可扩展和可维护;而工厂模式的目的是封装对象的创建过程,通过工厂类来统一创建对象,隐藏对象的具体实现细节。

2. 关注点不同:IoC关注于对象的依赖关系和组装过程,通过容器来管理对象的创建和依赖注入;而工厂模式关注于对象的创建过程,通过工厂类来创建对象。

3. 控制权不同:IoC将对象的控制权交给容器,由容器来负责对象的创建和管理;而工厂模式将对象的控制权交给工厂类,由工厂类来创建对象。

4. 使用方式不同:IoC通常通过依赖注入来实现,即容器在创建对象时自动注入依赖的其他对象;而工厂模式通常通过调用工厂类的方法来创建对象。

总的来说,IoC是一种更加综合和灵活的设计思想,它通过将对象的创建和管理交给容器来实现解耦和组装;而工厂模式是一种更加具体和专注的设计模式,它通过工厂类来统一创建对象。工厂模式可以作为IoC的一种实现方式之一。


抽象工厂模式

定义:在工厂模式的基础上使得每一个具体工厂可以生产多个产品。

代码实现

【设计模式】单例、工厂、装饰器、代理、适配器_第4张图片

简单来说,在工厂模式中的具体工厂下加上生产其他产品的代码就会变成抽象工厂。但是这样还是会回到简单工厂模式的问题:违反开闭原则。

Java的数据库访问API(如JDBC和JPA)使用了抽象工厂模式来创建数据库连接、会话等对象。不同的数据库厂商提供了不同的抽象工厂类,用于创建相应数据库的连接和会话对象。


装饰器模式

定义:动态地给一个对象添加一些额外的功能。就增加功能来说,装饰模式比生成子类更加灵活。

代码实现

【设计模式】单例、工厂、装饰器、代理、适配器_第5张图片

这个模式和代理模式有重合的思想,但是代理模式关注代理真正的类,而装饰器模式则是必须要扩展。总的来说,代理模式主要用于控制对对象的访问,而装饰模式主要用于给对象动态地添加功能。BufferedInputStream和BufferedOutputStream类就是对InputStream和OutputStream的装饰器,它们添加了缓冲功能。


代理模式

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

代码实现

【设计模式】单例、工厂、装饰器、代理、适配器_第6张图片

当然,如果仅仅是想实现功能增强也可以用上面装饰器模式的代码,再次强调代理模式关注的是对象访问的控制,而装饰器模式关注的是对功能的扩展。

下面对代理模式做个稍微详细的介绍

代理模式是一种结构型设计模式,它允许通过代理对象来控制对其他对象的访问。代理模式通过在代理对象和目标对象之间添加一层间接层,来实现对目标对象的间接访问和控制。

在代理模式中,有三个核心角色:
1. 目标对象(Subject):被代理的对象,它定义了代理对象所要代理的方法。
2. 代理对象(Proxy):代理目标对象,它持有对目标对象的引用,并在其自身的方法中调用目标对象的方法,可以在调用目标对象方法前后添加额外的逻辑。
3. 客户端(Client):使用代理对象的对象,它通过代理对象来访问目标对象。

代理模式可以实现以下功能和应用场景:
1. 访问控制:代理对象可以在调用目标对象的方法前后进行权限验证、安全检查等操作,从而对目标对象的访问进行控制。
2. 增强功能:代理对象可以在调用目标对象的方法前后添加额外的功能,如日志记录、性能监控、缓存等。
3. 远程代理:代理对象可以作为远程对象的代理,通过网络调用远程对象的方法。
4. 延迟加载:代理对象可以在需要时才创建和加载目标对象,从而实现延迟加载的效果。
5. AOP(面向切面编程):代理模式是AOP实现的基础,通过代理对象可以将横切逻辑(如事务管理、日志记录等)与业务逻辑分离,提高代码的可维护性和可重用性。

具体AOP的实现可以看我之前的文章。


适配器模式

定义:将一个类的接口变成客户端所期待的另一种接口,从而使原本因接口不匹配的而无法在一起工作的两个类能够在一起工作。

代码实现

【设计模式】单例、工厂、装饰器、代理、适配器_第7张图片

适配器模式和装饰器模式有什么不同?

适配器模式主要用于接口的转换和兼容,而装饰器模式主要用于给对象动态地添加功能。适配器模式通过适配器来使得原本不兼容的类能够协同工作。而装饰器模式通过在原有对象上添加装饰器来实现功能扩展。

SpringMVC就用到了这个模式

Spring MVC能够根据不同的处理器类型来选择合适的适配器,并将请求参数适配到处理器所需的形式,实现了请求的适配和分发。这种设计使得Spring MVC具有很高的灵活性和可扩展性,可以方便地支持不同类型的处理器和请求。下面来看看具体流程:

1、当一个请求到达DispatcherServlet时,DispatcherServlet会通过映射器根据请求的URL路径找到对应的处理器(Handler)。

2、然后,DispatcherServlet会通过HandlerAdapter来调用适配器的适配方法,将请求和处理器进行适配。

3、适配器会根据处理器的类型和特性,将请求参数进行适配和转换,以满足处理器的要求。

4、适配器将适配后的请求参数传递给处理器进行处理,并获取处理结果。

5、最后,适配器将处理结果返回给DispatcherServlet,由DispatcherServlet将结果响应给客户端。

题外话,一些SpringMVC的常见注解:

本回答由gpt.tool00.com代为生成,请认准本站。
Spring MVC提供了多个注解来简化和标识控制器(Controller)和处理器(Handler)的行为和功能。以下是一些常用的Spring MVC注解:

1. @Controller: 用于标识一个类为控制器,处理请求和生成响应。

2. @RequestMapping: 用于映射请求路径和处理器方法,指定请求的URL路径和HTTP方法。

3. @RequestParam: 用于绑定请求参数到方法参数,指定请求参数的名称和默认值。

4. @PathVariable: 用于绑定URL路径变量到方法参数,指定URL路径变量的名称。

5. @ResponseBody: 用于将方法返回值直接作为HTTP响应的内容,不进行视图解析。

6. @RequestBody: 用于将请求体的内容绑定到方法参数上,将请求体的内容转换为Java对象。

7. @Valid: 用于启用方法参数的校验,对方法参数进行数据验证。

你可能感兴趣的:(java,开发语言)