资讯详情

java面试常见设计模式

java常见的面试设计模式

  • 看这里,动画描述很好
  • 创建型模式
    • 工厂方法模式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • button
        • factory
        • Demo.java: 客户端代码
    • 抽象工厂模式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • buttons: 第一产品层次结构
        • checkboxes: 二是产品层次结构
        • factories
        • Demo
    • 生成器模式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • builders
        • cars
        • components
        • director
        • Demo.java: 客户端代码
    • 原型模式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • shapes: 形状列表
        • Demo.java: 克隆示例
    • 单例模式
      • 问题
      • 目的
      • 步骤
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • 基本单例(懒汉模式 延迟加载(单线程)
        • 基本单例(懒汉模式 延迟加载(多线程)
        • 延迟加载的线程安全单例
    • 其他
      • 比较工厂模式
        • 工厂
        • 构建方法
        • 静态构建 (或工厂) 方法
        • 简单工厂
        • 工厂方法
        • 抽象工厂
  • 结构型模式
    • 适配器模式
      • 运作方式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • round
        • square
        • adapters
        • Demo.java: 客户端代码
    • 组合模式
      • 运作方式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • shapes
        • editor
        • Demo.java: 客户端代码
    • 装饰模式
      • 问题
      • 运作方式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • Source
        • decorators
        • Demo.java: 客户端代码
    • 外观模式
      • 问题
      • 运作方式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
        • some_complex_media_library: 复杂的视频转换程序库
        • facade
        • Demo.java: 客户端代码
    • 代理模式
      • 问题
      • 运作方式
      • 目的
      • 结构
      • 场景
      • 优缺点
      • 示例代码
  • @Deprecated
    • 单例模式
      • 懒汉式单例
      • 饿汉式单例
      • 区别
    • 工厂模式
      • 应用
    • 适配器模式
    • 代理模式

看这里,动画描述很好

设计模式

创建型模式

提供了创建对象的机制,提升现有代码的灵活性和可重用性

工厂方法模式

在这里插入图片描述

目的

生产不同类型的产品 

针对不同类型的操作系统生成不同的 GUI 弹窗对象

结构

场景

无法预测对象的准确性别及其依赖关系coe>时, 可使用工厂方法。

工厂方法将创建产品的代码实际使用产品的代码分离, 从而能在不影响其他代码的情况下扩展产品创建部分代码。

例如, 如果需要向应用中添加一种新产品, 你只需要开发新的创建者子类, 然后重写其工厂方法即可。

优缺点

避免 创建者 和 具体产品 之间的  耦合 
单一职责 原则。  可以将 产品创建代码 放在 程序的单一位置,使 代码更容易维护 
开闭原则。 无需更改 现有客户端代码, 就可以 在程序中 引入 新的 产品类型
需要 引入 许多新的子类, 代码可能会因此变得更复杂

示例代码

button

package refactoring_guru.factory_method.example.buttons;

/** * Common interface for all buttons. */
public interface Button { 
         
    void render();
    void onClick();
}

package refactoring_guru.factory_method.example.buttons;

/** * HTML button implementation. */
public class HtmlButton implements Button { 
         

    public void render() { 
         
        System.out.println("<button>Test Button</button>");
        onClick();
    }

    public void onClick() { 
         
        System.out.println("Click! Button says - 'Hello World!'");
    }
}

package refactoring_guru.factory_method.example.buttons;

/** * Windows button implementation. */
public class WindowsButton implements Button { 
         
    ...

    public void render() { 
         
        ...
        onClick();
    }

    public void onClick() { 
         
        ...
    }
}

factory

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;

/** * Base factory class. Note that "factory" is merely a role for the class. It * should have some core business logic which needs different products to be * created. */
public abstract class Dialog { 
         

    public void renderWindow() { 
         
        // ... other code ...

        Button okButton = createButton();
        okButton.render();
    }

    /** * Subclasses will override this method in order to create specific button * objects. */
    public abstract Button createButton();
}

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;
import refactoring_guru.factory_method.example.buttons.HtmlButton;

/** * HTML Dialog will produce HTML buttons. */
public class HtmlDialog extends Dialog { 
         

    @Override
    public Button createButton() { 
         
        return new HtmlButton();
    }
}

package refactoring_guru.factory_method.example.factory;

import refactoring_guru.factory_method.example.buttons.Button;
import refactoring_guru.factory_method.example.buttons.WindowsButton;

/** * Windows Dialog will produce Windows buttons. */
public class WindowsDialog extends Dialog { 
         

    @Override
    public Button createButton() { 
         
        return new WindowsButton();
    }
}

Demo.java: 客户端代码

package refactoring_guru.factory_method.example;

import refactoring_guru.factory_method.example.factory.Dialog;
import refactoring_guru.factory_method.example.factory.HtmlDialog;
import refactoring_guru.factory_method.example.factory.WindowsDialog;

/** * Demo class. Everything comes together here. */
public class Demo { 
         
    private static Dialog dialog;

    public static void main(String[] args) { 
         
        configure();
        runBusinessLogic();
    }

    /** * The concrete factory is usually chosen depending on configuration or * environment options. */
    static void configure() { 
         
        if (System.getProperty("os.name").equals("Windows 10")) { 
         
            dialog = new WindowsDialog();
        } else { 
         
            dialog = new HtmlDialog();
        }
    }

    /** * All of the client code should work with factories and products through * abstract interfaces. This way it does not care which factory it works * with and what kind of product it returns. */
    static void runBusinessLogic() { 
         
        dialog.renderWindow();
    }
}

抽象工厂模式

一系列相关产品, 例如 椅子Chair 、 ​ 沙发Sofa和 咖啡桌Cof­fee­Table 。

系列产品的不同变体。 例如, 你可以使用 现代Mod­ern 、 ​ 维多利亚Vic­to­ri­an 、 ​ 装饰风艺术Art­Deco等风格生成 椅子 、 ​ 沙发和 咖啡桌 。

设法生成同一系列每件家具对象, 这样才能确保其风格一致。 如果顾客收到的家具风格不一样, 他们可不会开心。 客户端无需了解工厂类, 也不用管工厂类创建出的椅子类型。 无论是现代风格, 还是维多利亚风格的椅子, 对于客户端来说没有分别, 它只需要同一系列的桌椅就可以了。此外, 无论工厂返回的是何种椅子变体, 它都会和由同一工厂对象创建的沙发或咖啡桌风格一致

目的

创建一系列相关的对象

针对不同类型的操作系统生成不同 系列GUI 弹窗对象

结构

场景

需要与多个不同系列的相关产品交互, 但是由于无法提前获取相关信息, 或者出于对未来扩展性的考虑, 你不希望代码基于产品的具体类进行构建, 在这种情况下, 你可以使用抽象工厂。

抽象工厂为你提供了一个接口, 可用于创建每个系列产品的对象。 只要代码通过该接口创建对象, 那么你就不会生成与应用程序已生成的产品类型不一致的产品

在设计良好的程序中, 每个类仅负责一件事。 如果一个类与多种类型产品交互, 就可以考虑将工厂方法抽取到独立的工厂类具备完整功能的抽象工厂类中。

优缺点

可以确保 同一工厂 生成的产品 相互匹配
可以避免 客户端 和 具体产品 代码的耦合
单一职责原则。 可以将产品 生成代码 抽取到同一位置, 使得代码易于维护
开闭原则。 向应用程序中引入新产品变体时, 无需修改客户端代码。
由于采用该模式需要向应用中引入众多接口和类, 代码可能会比之前更加复杂。

示例代码

buttons: 第一个产品层次结构

public interface Button { 
         
    void paint();
}

public class MacOSButton implements Button { 
         

    @Override
    public void paint() { 
         
        System.out.println("You have created MacOSButton.");
    }
}

public class WindowsButton implements Button { 
         

    @Override
    public void paint() { 
         
        System.out.println("You have created WindowsButton.");
    }
}

checkboxes: 第二个产品层次结构

public interface Checkbox { 
         
    void paint();
}

public class MacOSCheckbox implements Checkbox { 
         

    @Override
    public void paint() { 
         
        System.out.println("You have created MacOSCheckbox.");
    }
}

public class WindowsCheckbox implements Checkbox { 
         

    @Override
    public void paint() { 
         
        System.out.println("You have created WindowsCheckbox.");
    }
}

factories

public interface GUIFactory { 
         
    Button createButton();
    Checkbox createCheckbox();
}

public class MacOSFactory implements GUIFactory { 
         

    @Override
    public Button createButton() { 
         
        return new MacOSButton();
    }

    @Override
    public Checkbox createCheckbox() { 
         
        return new MacOSCheckbox();
    }
}

public class WindowsFactory implements GUIFactory { 
         

    @Override
    public Button createButton() { 
         
        return new WindowsButton();
    }

    @Override
    public Checkbox createCheckbox() { 
         
        return new WindowsCheckbox();
    }
}

Demo

public class Application { 
         
    private Button button;
    private Checkbox checkbox;

    public Application(GUIFactory factory) { 
         
        button = factory.createButton();
        checkbox = factory.createCheckbox();
    }

    public void paint() { 
         
        button.paint();
        checkbox.paint();
    }
}

public class Demo { 
         

    /** * Application picks the factory type and creates it in run time (usually at * initialization stage), depending on the configuration or environment * variables. */
    private static Application configureApplication() { 
         
        Application app;
        GUIFactory factory;
        String osName = System.getProperty("os.name").toLowerCase();
        if (osName.contains("mac")) { 
         
            factory = new MacOSFactory();
            app = new Application(factory);
        } else { 
         
            factory = new WindowsFactory();
            app = new Application(factory);
        }
        return app;
    }

    public static void main(String[] args) { 
         
        Application app = configureApplication();
        app.paint();
    }
}

生成器模式

使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。

建造一栋简单的房屋, 首先你需要建造四面墙和地板 安装房门和一套窗户, 然后再建造一个屋顶。 但是如果你想要一栋更宽敞更明亮的房屋, 还要有院子和其他设施 (例如暖气、 排水和供电设备), 那又该怎么办呢?

最简单的方法是扩展 房屋基类, 然后创建一系列涵盖所有参数组合的子类。 但最终你将面对相当数量的子类。 任何新增的参数 (例如门廊类型) 都会让这个层次结构更加复杂

另一种方法则无需生成子类。 你可以在 房屋基类中创建一个包括所有可能参数的超级构造函数, 并用它来控制房屋对象。 这种方法确实可以避免生成子类, 但它却会造成另外一个问题。 生成器模式建议将对象构造代码从产品类中抽取出来, 并将其放在一个名为生成器的独立对象中 创建多个不同的生成器, 用不同方式实现一组相同的创建步骤。 然后你就可以在创建过程中使用这些生成器 (例如按顺序调用多个构造步骤) 来生成不同类型的对象第一个建造者使用木头和玻璃制造房屋, 第二个建造者使用石头和钢铁, 而第三个建造者使用黄金和钻石。 在调用同一组步骤后, 第一个建造者会给你一栋普通房屋, 第二个会给你一座小城堡, 而第三个则会给你一座宫殿

你可以进一步将用于创建产品的一系列生成器步骤调用抽取成为单独的主管类 主管类定义创建步骤的执行顺序, 而生成器则提供这些步骤的实现

目的

根据不同的属性需要,使用相同的步骤,创造拥有不同属性的对象
分步骤地 制造 不同型号的汽车, 使用 相同的生产过程 制造不同类型的产品 (汽车手册)

结构

场景

假设你的构造函数中有十个可选参数, 那么调用该函数会非常不方便; 因此, 你需要重载这个构造函数, 新建几个只有较少参数的简化版。 但这些构造函数仍需调用主构造函数, 传递一些默认数值来替代省略掉的参数

class Pizza { 
         
    Pizza(int size) { 
          ... }
    Pizza(int size, boolean cheese) { 
          ... }
    Pizza(int size, boolean cheese, boolean pepperoni) { 
          ... }
    // ...

生成器模式让你可以分步骤生成对象, 而且允许你仅使用必须的步骤。 应用该模式后, 你再也不需要将几十个参数塞进构造函数里了

如果你需要创建的各种形式的产品, 它们的制造过程相似仅有细节上的差异, 此时可使用生成器模式。

基本生成器接口中定义了所有可能的制造步骤具体生成器实现这些步骤来制造特定形式的产品。 同时, 主管类将负责管理制造步骤的顺序

优缺点

可以 分步创建 对象, 暂缓创建步骤 或 递归运行创建步骤。
生成 不同形式的产品 时, 可以 复用相同 的 制造代码。
单一职责 原则。 可以将 复杂构造代码 从 产品的 业务逻辑 中分离出来。
由于该模式需要新增多个类, 因此 代码 整体复杂程度 会有所增加

示例代码

主管 控制着 构造顺序。 它知道 制造 各种汽车型号 需要 调用 的 生产步骤 
	 它仅与 汽车的 通用接口进行交互。 这样就能 将不同类型的生成器 传递给主管了

最终结果 将 从生成器对象中 获得, 因为 主管 不知道 最终产品的类型
	只有 生成器对象知道 自己生成的产品 是什么

builders

public interface Builder { 
         
    void setCarType(CarType type);
    void setEngine(Engine engine);
    void setTripComputer(TripComputer tripComputer);
    void setGPSNavigator(GPSNavigator gpsNavigator);
}

public class CarBuilder implements Builder { 
         
    private CarType type;
    private Engine engine;
    private TripComputer tripComputer;
    private GPSNavigator gpsNavigator;

 	@Override
    public void setCarType(CarType type) { 
         
        this.type = type;
    }
...	

    public Car getResult() { 
         
        return new Car(type, seats, engine, transmission, tripComputer, gpsNavigator);
    }
}

public class CarManualBuilder implements Builder{ 
         
    private CarType type;
    private Engine engine;
    private TripComputer tripComputer;
    private GPSNavigator gpsNavigator;

    @Override
    public void setCarType(CarType type) { 
         
        this.type = type;
    }
...
    public Manual getResult() { 
         
        return new Manual(type, seats, engine, transmission, tripComputer, gpsNavigator);
    }
}

cars

public class Car { 
         
    private final CarType carType;
    private final Engine engine;
    private final TripComputer tripComputer;
    private final GPSNavigator gpsNavigator;
    private double fuel = 0;

    public Car(CarType carType, Engine engine, TripComputer tripComputer, GPSNavigator gpsNavigator) { 
         
        this.carType = carType;
        this.engine = engine;
        this.tripComputer = tripComputer;
        if (this.tripComputer != null) { 
         
            this.tripComputer.setCar(this);
        }
        this.gpsNavigator = gpsNavigator;
    }

    public CarType getCarType() { 
         
        return carType;
    }
...
}

public class Manual { 
         
    private final CarType carType;
    private final Engine engine;
    private final TripComputer tripComputer;
    private final GPSNavigator gpsNavigator;

    public Ma

标签: way系列圆形耦合连接器fit电源连接器系列

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台