【面试专题】设计模式篇①

1.工厂设计模式

工厂设计模式是一种创建型模式,它提供了一种创建对象的接口,但具体创建的对象类型可以在运行时决定。工厂设计模式主要解决的是创建对象的灵活性问题。

工厂设计模式主要包括简单工厂模式、工厂方法模式和抽象工厂模式三种。

  1. 简单工厂模式:通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。这种模式属于类的创新型模式,又叫静态工厂方法模式。简单工厂模式严重违背了"开闭原则",难以拓展。
  2. 工厂方法模式:定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口。这样进一步抽象化的好处是使得工厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。
  3. 抽象工厂模式:是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。

简单工厂模式:

java 复制代码
//抽象产品
interface Product {
    void doSomething();
}
 
//具体产品1
class ConcreteProduct1 implements Product {
    @Override
    public void doSomething() {
        System.out.println("具体产品1");
    }
}
 
//具体产品2
class ConcreteProduct2 implements Product {
    @Override
    public void doSomething() {
        System.out.println("具体产品2");
    }
}
 
//工厂类
class Factory{
    public static Product createProduct(int type) {
        switch (type) {
            case 1:
                return new ConcreteProduct1();
            case 2:
                return new ConcreteProduct2();
            default:
                return null;
        }
    }
}
 
//测试类
public class Test {
    public static void main(String[] args) {
        Factory.createProduct(1).doSomething();//输出具体产品1
        Factory.createProduct(2).doSomething();//输出具体产品2
    }
}

工厂方法模式:

java 复制代码
//抽象产品
interface Product{
    void doSomething();
}
 
//具体产品1
class ConcreteProduct1 implements Product{
    @Override
    public void doSomething() {
        System.out.println("具体产品1");
    }
}
 
//具体产品2
class ConcreteProduct2 implements Product{
    @Override
    public void doSomething() {
        System.out.println("具体产品2");
    }
}
 
//抽象工厂
interface Factory {
    Product createProduct();
}
 
//具体工厂1
class ConcreteFactory1 implements Factory{
    @Override
    public Product createProduct() {
        return new ConcreteProduct1();
    }
}
 
//具体工厂2
class ConcreteFactory2 implements Factory{
    @Override
    public Product createProduct() {
        return new ConcreteProduct2();
    }
}
 
//测试类
public class Test {
    public static void main(String[] args) {
        Factory factory1 = new ConcreteFactory1();
        factory1.createProduct().doSomething(); //输出具体产品1
        Factory factory2 = new ConcreteFactory2();
        factory2.createProduct().doSomething(); //输出具体产品2
    }
}

抽象工厂模式:

java 复制代码
//抽象产品A
interface ProductA{
    void doSomething();
}
 
//具体产品A1
class ConcreteProductA1 implements ProductA{
    @Override
    public void doSomething() {
        System.out.println("具体产品A1");
    }
}
 
//具体产品A2
class ConcreteProductA2 implements ProductA{
    @Override
    public void doSomething() {
        System.out.println("具体产品A2");
    }
}
 
//抽象产品B
interface ProductB{
    void doSomething();
}
 
//具体产品B1
class ConcreteProductB1 implements ProductB{
    @Override
    public void doSomething() {
        System.out.println("具体产品B1");
    }
}
 
//具体产品B2
class ConcreteProductB2 implements ProductB{
    @Override
    public void doSomething() {
        System.out.println("具体产品B2");
    }
}
 
//抽象工厂
interface AbstractFactory{
    ProductA createProductA();
    ProductB createProductB();
}
 
//具体工厂1
class ConcreteFactory1 implements AbstractFactory{
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA1();
    }
    @Override
    public ProductB createProductB() {
        return new ConcreteProductB1();
    }
}
 
//具体工厂2
class ConcreteFactory2 implements AbstractFactory{
    @Override
    public ProductA createProductA() {
        return new ConcreteProductA2();
    }
    @Override
    public ProductB createProductB() {
        return new ConcreteProductB2();
    }
}
 
//测试类
public class Test {
    public static void main(String[] args) {
        AbstractFactory factory1 = new ConcreteFactory1();
        factory1.createProductA().doSomething(); //输出具体产品A1
        factory1.createProductB().doSomething(); //输出具体产品B1
        AbstractFactory factory2 = new ConcreteFactory2();
        factory2.createProductA().doSomething(); //输出具体产品A2
        factory2.createProductB().doSomething(); //输出具体产品B2
    }
}

2.策略模式

策略模式是一种行为型设计模式,它允许在运行时选择算法的行为。在Java中,可以通过接口和抽象类来实现策略模式。以下是一个简单的示例,展示应该如何使用Java编写策略模式。

首先,定义一个接口,该接口将定义策略算法的方法。

public interface Strategy {
    int execute(int num1, int num2);
}

接下来,创建实现该接口的不同策略类。

public class Add implements Strategy {
    public int execute(int num1, int num2) {
        return num1 + num2;
    }
}

public class Subtract implements Strategy {
    public int execute(int num1, int num2) {
        return num1 - num2;
    }
}

public class Multiply implements Strategy {
    public int execute(int num1, int num2) {
        return num1 * num2;
    }
}

然后,在主程序中,创建一个Context类,该类使用指定的策略执行算法。

public class Context {

    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public int executeStrategy(int num1, int num2) {
        return strategy.execute(num1, num2);
    }
}

最后,实例化不同的策略并将它们传递给Context类。

public class StrategyPatternExample {

    public static void main(String[] args) {
        Context context = new Context(new Add());
        System.out.println("10 + 5 = " + context.executeStrategy(10, 5));

        context = new Context(new Subtract());
        System.out.println("10 - 5 = " + context.executeStrategy(10, 5));

        context = new Context(new Multiply());
        System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
    }
}

输出:

10 + 5 = 15
10 - 5 = 5
10 * 5 = 50

这个例子演示了如何实现策略模式,它允许在运行时选择算法的行为。

3.策略模式+工厂模式 实现登录

工厂方法模式是一种创建型模式,它将对象的创建委托给工厂类,由工厂类负责创建具体的对象实例。而策略模式是一种行为型模式,它定义了一系列算法,并将每个算法封装起来,使它们可以互换。

通过工厂方法模式,我们可以根据输入的参数,创建出对应的策略对象,然后通过策略对象来实现登录功能。具体实现如下:

1.创建策略接口,定义登录方法。

java 复制代码
public interface LoginStrategy {
    boolean login(String username, String password);
}

2.创建具体的策略实现类,实现登录方法。

java 复制代码
public class EmailLoginStrategy implements LoginStrategy {
    @Override
    public boolean login(String username, String password) {
        // 基于邮箱的登录逻辑
        return true;
    }
}

public class PhoneLoginStrategy implements LoginStrategy {
    @Override
    public boolean login(String username, String password) {
        // 基于手机号的登录逻辑
        return true;
    }
}

public class UsernameLoginStrategy implements LoginStrategy {
    @Override
    public boolean login(String username, String password) {
        // 基于用户名的登录逻辑
        return true;
    }
}

3.创建工厂接口,定义创建策略对象的方法。

java 复制代码
public interface LoginStrategyFactory {
    LoginStrategy createLoginStrategy(String type);
}

4.创建具体的工厂实现类,根据输入的参数创建对应的策略对象。

java 复制代码
public class LoginStrategyFactoryImpl implements LoginStrategyFactory {
    @Override
    public LoginStrategy createLoginStrategy(String type) {
        switch (type) {
            case "email":
                return new EmailLoginStrategy();
            case "phone":
                return new PhoneLoginStrategy();
            case "username":
                return new UsernameLoginStrategy();
            default:
                return null;
        }
    }
}

5.最终的登录类中,调用工厂方法来创建对应的策略对象,并调用登录方法。

java 复制代码
public class Login {
    public boolean login(String type, String username, String password) {
        LoginStrategyFactory factory = new LoginStrategyFactoryImpl();
        LoginStrategy strategy = factory.createLoginStrategy(type);
        return strategy.login(username, password);
    }
}

这样,我们就可以根据输入的参数,动态地创建出对应的策略对象来实现登录功能。而且当需要增加新的登录方式时,只需要添加新的策略类和工厂方法即可。

4.责任链模式

责任链模式可以用于将多个处理请求的对象连接起来,形成一条处理链,将请求沿着这条链传递,直到有对象能够处理该请求为止,从而实现请求的处理和解耦的目的。下面以一个简单的示例说明如何在Java中实现责任链设计模式。

java 复制代码
abstract class Handler {
     protected Handler handler;

     void setNext(Handler handler){
         this.handler = handler;

     }

    public abstract void process(OrderInfo order);


}
java 复制代码
import java.math.BigDecimal;

public class OrderInfo {
    private String  productId;
    private String userId;
    private BigDecimal amount;


    public String getProductId() {
        return productId;
    }

    public void setProductId(String productId) {
        this.productId = productId;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }
}
java 复制代码
public class OrderValidition extends Handler {

    @Override
    public void process(OrderInfo order) {
        System.out.println("OrderValidition--------");
        handler.process(order);
    }
}
java 复制代码
public class OrderFill extends Handler{
    @Override
    public void process(OrderInfo order) {
        System.out.println("OrderFill----");
        handler.process(order);
    }
}
java 复制代码
public class OderAmountCalcuate extends Handler {
    @Override
    public void process(OrderInfo order) {
        System.out.println("OderAmountCalcuate----");
        handler.process(order);
    }
}
java 复制代码
public class OderCreate extends Handler {

    @Override
    public void process(OrderInfo order) {
        System.out.println("OderCreate ----");

    }
}
java 复制代码
public class Client {
    public static void main(String[] args) {

        OrderValidition orderValidition = new OrderValidition();
        OrderFill orderFill = new OrderFill();
        OderAmountCalcuate oderAmountCalcuate = new OderAmountCalcuate();
        OderCreate oderCreate = new OderCreate();
        
        orderValidition.setNext(orderFill);
        orderFill.setNext(oderAmountCalcuate);
        oderAmountCalcuate.setNext(oderCreate);

        orderValidition.process(new OrderInfo());


    }
}
java 复制代码
OrderValidition--------
OrderFill----
OderAmountCalcuate----
OderCreate ----

5.单例模式

推荐视频:【单例模式】猛男因不懂单例模式,被面试官无情嘲讽_哔哩哔哩_bilibili

单例模式是一种创建型设计模式,用于确保类只有一个实例存在,并提供一个全局访问点。它的主要思想是,一个类只允许创建一个对象(或实例),并提供一个访问该对象的全局访问点。

单例模式的应用场景包括:

  1. 全局唯一的配置管理器。

  2. 全局唯一的状态管理器。

  3. 数据库连接池。

  4. 多线程池。

  5. 全局唯一的日志记录器。

  6. 具有特殊限制或唯一性要求的资源管理器。

单例模式的实现方式有多种,包括饿汉式单例、懒汉式单例、双重校验锁单例、静态内部类单例等。其中,饿汉式和懒汉式是最基础的两种实现方式。

1.饿汉式单例模式

饿汉式单例模式在类加载时即创建一个实例,不存在线程安全问题,但会影响性能,因为即使不需要使用该实例,也会一直占用内存。

java 复制代码
public class Singleton {
    // 静态实例,类加载时即创建
    private static Singleton instance = new Singleton();
    // 私有构造方法,防止外部创建实例
    private Singleton() {}
    // 全局访问方法
    public static Singleton getInstance() {
        return instance;
    }
}
2.懒汉式单例模式

懒汉式单例模式在第一次访问实例时才创建,但存在线程安全问题,需要进行加锁处理。

java 复制代码
public class Singleton {
    // 私有静态实例,延迟加载
    private static Singleton instance = null;
    // 私有构造方法,防止外部创建实例
    private Singleton() {}
    // 全局访问方法,加锁保证线程安全
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}
3.双重校验锁单例

双重校验锁单例是一种常用的单例模式实现方式,它既保证了线程安全性,又提高了效率,下面是Java实现双重校验锁单例的代码:

java 复制代码
public class Singleton {
    // volatile修饰的变量在多线程环境下保证可见性和有序性
    private volatile static Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                // 双重校验锁,第一个if判断为了避免不必要的同步,第二个if保证同步情况下只有一个instance被创建
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

上述代码中,instance变量使用了volatile关键字修饰,保证在多线程环境下对instance的读写操作都是可见的,避免出现线程A修改了instance变量值而线程B不可见的情况。

getInstance()方法中,第一个if判断为了避免多个线程同时进入synchronized代码块,进而造成系统资源的浪费。第二个if保证了在同步代码块中,只有一个instance被创建,避免线程安全问题的发生。

总之,使用双重校验锁单例可以保证线程安全性和效率,是一种常用的单例模式实现方式。

相关推荐
希忘auto11 分钟前
详解MySQL安装
java·mysql
娅娅梨14 分钟前
C++ 错题本--not found for architecture x86_64 问题
开发语言·c++
汤米粥20 分钟前
小皮PHP连接数据库提示could not find driver
开发语言·php
冰淇淋烤布蕾22 分钟前
EasyExcel使用
java·开发语言·excel
拾荒的小海螺29 分钟前
JAVA:探索 EasyExcel 的技术指南
java·开发语言
Jakarta EE1 小时前
正确使用primefaces的process和update
java·primefaces·jakarta ee
马剑威(威哥爱编程)1 小时前
哇喔!20种单例模式的实现与变异总结
java·开发语言·单例模式
白-胖-子1 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
好睡凯1 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
java—大象1 小时前
基于java+springboot+layui的流浪动物交流信息平台设计实现
java·开发语言·spring boot·layui·课程设计