代码随想录题解
代码随想录刷题1数组1.1二分查找1.1.1二分查找关键词:有序(升序),不重复 思路:有序,不重复,马上就可以想到是二分查找,不断的二分缩小范围就可以找到目标值 1234567891011121314151617181920class Solution { public int search(int[] nums, int target) { if(target < nums[0] || target > nums[nums.length - 1]){ return -1; } int left = 0; int right = nums.length -1; while(left <= right){ int mid = left + ((right - left) >> 1); if (target > nums[mid]){ ...
装饰器模式
装饰器模式装饰器模式通过将对象放入一个装饰器类,再将装饰器类放入另一个装饰器类,以此类推形成装饰器包装链,这样就可以在不改变原对象的前提下动态的添加新的行为 概述先来看一个小例子 定义抽象类 123public interface Component { void operation();} 定义具体的被装饰类,实现抽象类方法 123456public class ConcreteComponent implements Component { @Override public void operation() { System.out.println("ConcreteComponent is doing something..."); }} 定义装饰器抽象类 12345678910public abstract class Decorator implements Component { protected Component...
原型设计模式
原型设计模式原型设计模式就是在运行过程中,通过拷贝创建新的对象,而不是通过实例化一个类,这样可以减少对象的创建成本,适用于以下场景 对象创建的成本较高,例如需要大量的计算和网络IO 需要创建大量相似的对象 需要动态的创建对象并且希望避免传统的创建方式 在这些场景,原型设计模式可以显著提升系统性能和可拓展性,因为他可以避免频繁的对象创建和销毁 实现方式浅拷贝浅拷贝是指在复制对象时,只复制对象的基本数据类型的值和引用类型的地址,不复制引用类型指向的对象本身 浅拷贝的实现可以适用直接赋值或clone方法 1234567891011121314151617181920212223public class ShallowClone implements Cloneable{ private Student student; public void setStudent(Student student) { this.student = student; } public Student getStudent()...
享元模式
享元模式享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。 具体来讲,当一个系统中存在**大量重复对象的时候,如果这些重复的对象是不可变对象,我们就可以利用享元模式将对象设计成享元,**在内存中只保留一份实例,供多处代码引用。这样可以减少内存中对象的数量,起到节省内存的目的。实际上,不仅仅相同对象可以设计成享元,对于相似对象,我们也可以将这些对象中相同的部分(字段)提取出来,设计成享元,让这些大量相似对象引用这些享元。 Integer是一个经典的享元模式应用 123456Integer i1 = 56;Integer i2 = 56;Integer i3 = 129;Integer i4 = 129;System.out.println(i1 i2);System.out.println(i3 i4); 我们来看看这段代码,首先我们可以很明确的知道i1和i2都是56,i3和i4都是129,所以从数值上看他们都是相等的,但是他们的结果都是true吗? 其实不然,这里...
适配器模式
适配器模式适配器模式用于解决两个不兼容接口之间的问题,适配器可以将一个类的接口转换为客户端所需要的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。 适配器设计模式中主要包含了四个角色: 目标接口(Target):这是客户端所希望使用的接口,它定义了特定领域的操作和方法 需要适配的类(Adaptee):这是一个已存在的类,它具有客户端需要的功能,但其接口与目标接口不兼容。适配器的目标是使这个类的功能能够通过目标接口使用。 适配器(Adapter):这是适配器模式的核心角色,它实现了目标接口并持有需要适配的类的一个实例。适配器通过封装Adaptee的功能,使其能够满足Target接口的要求。 客户端(Client):这是使用目标接口的类。客户端与目标接口进行交互,不直接与需要适配的类交互。通过使用适配器,客户端可以间接地使用需要适配的类的功能 适配器模式的有两种实现方法 类适配器类适配器通过继承实现适配器的功能 1234567891011121314151617181920212223// 目标接口interface Target { void...
建造者模式
建造者模式建造者模式主要将构造器和set方法组合,打通整个对象创建的过程,创建者模式主要包含以下四个角色 产品(Product):要创建的复杂对象 抽象创建者(Abstract Builder):定义构建产品的接口,通常包含创建和获取产品的方法 具体创建者(Concrete Builder):实现抽象创建者定义的接口,为产品的各个部分提供具体实现 指挥者(Director):负责调用具体创建者来构建产品的各个部分,控制构建过程。 用法假设我们要创建一个html文档对象,它包含了标题,段落,图像等元素,我们可以用建造者模式创建对象 产品12345678910111213141516171819public class HtmlDocument { private String header = ""; private String body = ""; private String footer = ""; public void addHeader(String header)...
观察者模式
...
工厂模式
工厂模式简单工厂(Simple Factory)假设有这样一个场景,我们要根据url进行资源的加载,如果我们把所有的加载实现都写在同一个load方法中,那么方法就会非常的长,而且拓展性很差 123456789101112131415161718192021222324252627public class ResourceLoader { public Resource load(String filePath) { String prefix = getResourcePrefix(filePath); Resource resource = null; if ("http".equals(type)) { // ..发起请求下载资源... 可能很复杂 return new Resource(url); } else if ("file".equals(type)) { //...
单例模式
单例模式单例设计模式(Singleton Design Pattern)就是一个类只允许创建一个对象。 为什么要使用单例? 单例可以表示全局唯一,一些数据在系统中应该且只能保存一份,那就应该设计为单例类,例:配置类,全局计数器 处理资源访问冲突(如日志写文件如果多线程同时写就会导致覆盖问题) 如何获取一个单例常见的单例获取方式大致可以分为懒汉式和饿汉式,除此外还有其他获取的方式,但是无论是哪种方式都要注意以下几点 构造器需要私有化 暴露公共接口获取单例对象 是否支持懒加载 是否线程安全 下面讲讲单例模式的几种实现方式 饿汉式饿汉式的实现方法比较简单,在类加载的时候已经创建完毕。 123456789101112131415161718public class EagerSingleton implements Serializable { private static EagerSingleton instance = new EagerSingleton(); /** * 私有构造函数 */ private EagerSingleton()...
代理模式
代理模式概念代理模式为其他对象提供一个代理,然后可以通过这个代理对象控制原对象的访问,代理对象只是作为访问者和被代理对象之间的一个中介 代理分为静态代理和动态代理,静态代理是指代理类在编译时就已经确定,而动态代理是指代理类在运行时动态生成,下面通过一些场景说一下 静态代理应用场景缓存代理缓存代理可以为一些耗时的重复的操作提供缓存,从而提高程序的运行效率,首先我们定义一个数据查询接口 123public interface DataQuery { String query(String queryKey);} 然后实现一个真实查询类 1234567public class DatabaseDataQuery implements DataQuery { @Override public String query(String queryKey) { // 查询数据库并返回结果 return "Result from database: " + queryKey; ...