当前位置: 首页 > news >正文

p2f网站系统免费文档模板网站

p2f网站系统,免费文档模板网站,2021年国家大事件有哪些,现在哪些网站做外贸的好做文章目录 一 创建型模式1.1 单例模式的设计与实现1.1.1 饿汉式模式1.1.2 懒汉式单例模式1.1.3 懒汉式单例模式完善1.1.4 双重检测锁式1.1.4.1 volatile关键字1.1.4.2 在双重检查锁定中的作用 1.1.5 静态内部类式单例模式1.1.6 枚举式单例模式1.1.7 反射暴力破解解决方案1.1.8 序… 文章目录 一 创建型模式1.1 单例模式的设计与实现1.1.1 饿汉式模式1.1.2 懒汉式单例模式1.1.3 懒汉式单例模式完善1.1.4 双重检测锁式1.1.4.1 volatile关键字1.1.4.2 在双重检查锁定中的作用 1.1.5 静态内部类式单例模式1.1.6 枚举式单例模式1.1.7 反射暴力破解解决方案1.1.8 序列化和反序列化的解决方案 1.2 单例模式的经典应用1.3 单例模式的业务实现1.4 工厂模式1.4.1 工厂模式的设计与实现1.4.2 简单工厂模式1.4.3 工厂方法模式1.4.4 抽象工厂模式1.4.5 三者对比1.4.6 工厂模式的经典应用1.4.7 工厂模式的业务实现1.4.7.1 简单工厂模式1.4.7.2 工厂方法模式1.4.7.3 抽象工厂模式 1.5 建造者模式1.5.1 建造者模式的设计与实现1.5.2 适用场景1.5.3 优缺点1.5.4 代码示例1.5.5 建造者模式经典应用1.5.6 建造者模式和工厂模式的区别 1.6 原型模式1.6.1 原型模式的设计与实现1.6.2 浅克隆方式1.6.3 深克隆方式1.6.4 序列化方式深克隆1.6.4.1 序列化深拷贝的原理1.6.4.2 适用前提1.4.6.3 以 Java 原生序列化为例1.4.6.4 复杂引用关系的深拷贝1.4.6.5 其他序列化方案对比 1.6.5 原型模式的经典应用1.6.6 原型模式的业务实现 一 创建型模式 创建型模式对象的创建问题封装复杂的创建过程以及解耦对象的对象和代码的使用过程。 单例模式负责创建全局唯一的对象工厂模式创建类型不同但相关的对象【父子类关系-继承接口】建造者模式创建复杂对象原型模式针对创建成本较大的对象利用对已有对象的复制方式进行创建达到节省创建时间的目录。 1.1 单例模式的设计与实现 单例模式的核心是保证一个类只有一个实例并且提供一个访问实例的全局访问点。单例模式可以分为5种实现方式。 实现方式优缺点饿汉式线程安全调用效率高不能延迟加载懒汉式线程安全调用效率不高能延迟加载双重检测锁式在懒汉式的基础上解决并发问题静态内部类式线程安全资源利用率高可以延时加载枚举单例线程安全调用效率高不能延迟加载 1.1.1 饿汉式模式 饿汉式单例模式类加载的时候立即实例化对象实现的步骤是先私有化构造方法对外提供唯一的静态入口方法。 package com.yang.designmode.singleton;/*** 单例饿汉式模式* 线程安全单例对象在类装载的时候创建只创建一次所以是线程安全的如果后面没有使用会造成资源浪费* 唯一的对象防止别人通过new关键字创建对象* 需要提供私有化所有的构造器* 提供全局的访问点提供一个共有的static方法 返回单例对象*/ public class HungrySingleton {private static final HungrySingleton instancenew HungrySingleton();//私有化构造方法private HungrySingleton() {}//对外提供共有方法public static HungrySingleton getInstance(){return instance;} }package com.yang.designmode.singleton;public class HungrySingletonTest {public static void main(String[] args) {HungrySingleton instance_0 HungrySingleton.getInstance();HungrySingleton instance_1 HungrySingleton.getInstance();System.out.println(instance_0);System.out.println(instance_1);System.out.println(instance_0instance_1);} }1.1.2 懒汉式单例模式 package com.yang.designmode.singleton;/*** 懒汉式单例线程不安全 在需要使用时加载对应的单例对象*/ public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}public static LazySingleton getInstance() throws InterruptedException {//通过构造器完成对象的创建if (instance null) {Thread.sleep(10);instance new LazySingleton();}return instance;} }package com.yang.designmode.singleton;public class LazySingletonTest {public static void main(String[] args) {System.out.println(懒汉式单例并发场景测试);for (int i 0; i 100; i) {new Thread(() - {try {System.out.println(LazySingleton.getInstance());} catch (InterruptedException e) {throw new RuntimeException(e);}}).start();}} }线程不安全初级创建在并发场景下可能出现创建多个实例的问题。 懒汉式单例并发场景测试 com.yang.designmode.singleton.LazySingleton210b77ce com.yang.designmode.singleton.LazySingleton5359f47c com.yang.designmode.singleton.LazySingleton604f3632 com.yang.designmode.singleton.LazySingleton7d70ea4f com.yang.designmode.singleton.LazySingleton255d3263 com.yang.designmode.singleton.LazySingleton604f3632 com.yang.designmode.singleton.LazySingleton9a67d48 com.yang.designmode.singleton.LazySingleton48fc694 com.yang.designmode.singleton.LazySingleton19eacfad com.yang.designmode.singleton.LazySingleton44ea945f com.yang.designmode.singleton.LazySingleton56c601fe com.yang.designmode.singleton.LazySingleton45534694 com.yang.designmode.singleton.LazySingleton4594d87 com.yang.designmode.singleton.LazySingleton45534694 com.yang.designmode.singleton.LazySingleton4594d87 com.yang.designmode.singleton.LazySingleton412be3e41.1.3 懒汉式单例模式完善 在创建对象的方法中添加synchronized锁保证创建的唯一性。 public static synchronized LazySingleton getInstance() throws InterruptedException {//通过构造器完成对象的创建if (instance null) {Thread.sleep(10);instance new LazySingleton();}return instance; }1.1.4 双重检测锁式 package com.yang.designmode.singleton;/*** 双重检查锁定Double-Check Locking实现的单例模式。* 保证了多线程环境下的单例实例创建并且只进行一次同步操作提高性能。*/ public class DoubleCheckSingleton {/*** 使用 volatile 关键字确保多线程环境下的可见性和禁止指令重排序。* 保证在所有线程中该变量的值是一致的。*/private static volatile DoubleCheckSingleton instance;/*** 私有构造函数防止外部通过 new 创建实例。*/private DoubleCheckSingleton(){}/*** 获取单例对象的方法。* 使用双重检查锁定机制来延迟初始化单例对象。** return 单例对象*/public static DoubleCheckSingleton getInstance(){// 第一次检查如果 instance 已经被初始化则直接返回避免不必要的同步开销if(instance null){// 同步类锁保证只有一个线程进入代码块synchronized (DoubleCheckSingleton.class){// 第二次检查确保只有一个实例被创建if(instance null){// 创建单例对象instance new DoubleCheckSingleton();}}}return instance;} }1.1.4.1 volatile关键字 在Java中volatile是一个关键字用于修饰变量确保多线程环境下的可见性和禁止指令重排序。 private static volatile DoubleCheckSingleton instance;✅ 保证可见性Visibility 在多线程环境中每个线程可能会有自己的本地缓存CPU 缓存不加 volatile 时读写操作可能只发生在本地缓存中。使用 volatile 后每次读取都会从主内存中获取最新值每次写入也会立即刷新到主内存中从而保证多个线程看到的是同一个值。 ✅ 禁止指令重排序Instruction Reordering 在创建对象时JVM 可能会对指令进行优化重排例如 instance new DoubleCheckSingleton();实际上分为三步 分配内存空间调用构造函数初始化对象将引用指向分配的内存地址。 如果没有 volatile有可能线程 A 执行完步骤 1 和 3还没执行步骤 2此时线程 B 检查 instance ! null 并使用它就会得到一个未完全初始化的对象导致错误。使用 volatile 后会插入内存屏障防止上述重排序问题。 1.1.4.2 在双重检查锁定中的作用 在双重检查锁定Double-Checked Locking中 public static DoubleCheckSingleton getInstance(){if(instance null){synchronized (DoubleCheckSingleton.class){if(instance null){instance new DoubleCheckSingleton();}}}return instance; }第一次检查 if(instance null) 是为了提高性能避免每次都进入同步块。第二次检查是在同步块内再次确认是否已创建实例。如果 instance 没有被 volatile 修饰就可能发生前面提到的“读取到未完全初始化的实例”的问题。 因此加上 volatile 是 必须且关键的操作否则双重检查锁定模式在多线程下是不安全的。 关键点描述volatile 关键字保证变量在多线程之间的可见性和有序性单例模式中为何需要防止因指令重排导致线程拿到未初始化完成的对象推荐保留 volatile否则可能导致严重并发问题 1.1.5 静态内部类式单例模式 package com.yang.designmode.singleton;/*** 静态内部类单例模式*/ public class StaticInnerSingleton {//私有化构造器private StaticInnerSingleton() {}//静态内部类private static class SingletonClassInstance {//声明一个外部类的静态成员变量并且通过new 关键字创建对象和赋值private static final StaticInnerSingleton instance new StaticInnerSingleton();}public static StaticInnerSingleton getInstance() {return SingletonClassInstance.instance;} }public class StaticInnerSingletonTest {public static void main(String[] args) {System.out.println(静态内部类单例并发场景测试);for (int i 0; i 100; i) {new Thread(() - {System.out.println(StaticInnerSingleton.getInstance());}).start();}} }1.1.6 枚举式单例模式 枚举的实例化由JVM控制在类加载完成就完成了没常量的初始化。枚举量默认被public static final修饰确保实例的唯一和不可变。 package com.yang.designmode.singleton;public enum EnumSingleton {INSTANCE;private int value;public int getValue() {return value;}public void setValue(int value) {this.value value;} }package com.yang.designmode.singleton;public class EnumSingletonTest {public static void main(String[] args) {for (int i0;i10;i){new Thread(()-{System.out.println(EnumSingleton.INSTANCE);}).start();}System.out.println();EnumSingleton instance_1 EnumSingleton.INSTANCE;instance_1.setValue(20);System.out.println(instance_1.getValue());EnumSingleton instance_2 EnumSingleton.INSTANCE;System.out.println(instance_2.getValue());System.out.println(instance_1 instance_2);} }1.1.7 反射暴力破解解决方案 在Java中反射机制可以访问并修改类的私有构造函数、字段和方法这可能导致单例模式被破坏。为了解决这个问题可以在构造函数中添加一个检查逻辑如果实例已经被创建则抛出异常以防止通过反射创建新的实例。 在私有构造函数中添加一个检查逻辑 如果instance不为 null说明实例已经被创建。抛出运行时异常阻止通过反射创建新的实例。 private DoubleCheckSingletonDestory(){if(instance ! null){// 说明有人想要破坏单例特性创建多个实例throw new RuntimeException(DoubleCheckSingletonDestory.class 单例模式不允许创建多个实例);} }if (instance ! null)检查是否已经存在一个实例。throw new RuntimeException(...)如果实例已经存在抛出异常阻止创建新的实例。 正常情况下第一次调用 getInstance() 会成功创建实例。如果尝试通过反射调用私有构造函数来创建新实例将会触发异常从而保护单例模式不被破坏。 在 main 方法中尝试通过反射创建实例会抛出异常 public static void main(String[] args) throws Exception {// 正常创建单例对象DoubleCheckSingletonDestory instance_1 DoubleCheckSingletonDestory.getInstance();System.out.println(instance_1);// 通过反射创建单例对象ClassDoubleCheckSingletonDestory doubleCheckSingletonDestoryClass DoubleCheckSingletonDestory.class;ConstructorDoubleCheckSingletonDestory declaredConstructor doubleCheckSingletonDestoryClass.getDeclaredConstructor(null);// 放开私有的访问权限declaredConstructor.setAccessible(true);try {DoubleCheckSingletonDestory instance_2 declaredConstructor.newInstance(null);System.out.println(instance_2);} catch (Exception e) {System.out.println(反射创建实例失败: e.getMessage());} }declaredConstructor.setAccessible(true)允许访问私有构造函数。declaredConstructor.newInstance(null)尝试通过反射创建实例但由于构造函数中的检查逻辑最终会抛出异常。 完整代码 package com.yang.designmode.singleton;import java.lang.reflect.Constructor;/*** 双重检查锁定Double-Check Locking实现的单例模式。* 保证了多线程环境下的单例实例创建并且只进行一次同步操作提高性能。*/ public class DoubleCheckSingletonDestory {/*** 使用 volatile 关键字确保多线程环境下的可见性和禁止指令重排序。* 保证在所有线程中该变量的值是一致的。*/private static volatile DoubleCheckSingletonDestory instance;/*** 私有构造函数防止外部通过 new 创建实例。*/private DoubleCheckSingletonDestory(){if(instance!null){//说明有人想要破坏单例特性创建多个实例throw new RuntimeException(DoubleCheckSingletonDestory.class单例模式不允许创建多个实例);}}/*** 获取单例对象的方法。* 使用双重检查锁定机制来延迟初始化单例对象。** return 单例对象*/public static DoubleCheckSingletonDestory getInstance(){// 第一次检查如果 instance 已经被初始化则直接返回避免不必要的同步开销if(instance null){// 同步类锁保证只有一个线程进入代码块synchronized (DoubleCheckSingletonDestory.class){// 第二次检查确保只有一个实例被创建if(instance null){// 创建单例对象//潜在的安全问题 线程安全原子性、可见性、顺序性/*1. 分配内存空间2. 初始化对象3. 将 instance 指向分配的内存地址*/instance new DoubleCheckSingletonDestory();}}}return instance;}public static void main(String[] args) throws Exception {// 正常创建单例对象DoubleCheckSingletonDestory instance_1 DoubleCheckSingletonDestory.getInstance();System.out.println(instance_1);//通过反射创建单例对象ClassDoubleCheckSingletonDestory doubleCheckSingletonDestoryClass DoubleCheckSingletonDestory.class;ConstructorDoubleCheckSingletonDestory declaredConstructor doubleCheckSingletonDestoryClass.getDeclaredConstructor(null);// 放开私有的访问权限declaredConstructor.setAccessible(true);DoubleCheckSingletonDestory instance_2 declaredConstructor.newInstance(null);System.out.println(instance_2);} }1.1.8 序列化和反序列化的解决方案 通过序列化和反序列化破坏单例模式的案例 import java.io.*; /*** 双重检查锁定Double-Check Locking实现的单例模式。* 保证了多线程环境下的单例实例创建并且只进行一次同步操作提高性能。*/ public class DoubleCheckSingletonSerializable implements Serializable {/*** 使用 volatile 关键字确保多线程环境下的可见性和禁止指令重排序。* 保证在所有线程中该变量的值是一致的。*/private static volatile DoubleCheckSingletonSerializable instance;/*** 私有构造函数防止外部通过 new 创建实例。*/private DoubleCheckSingletonSerializable(){if(instance!null){//说明有人想要破坏单例特性创建多个实例throw new RuntimeException(DoubleCheckSingletonSerializable.class单例模式不允许创建多个实例);}}/*** 获取单例对象的方法。* 使用双重检查锁定机制来延迟初始化单例对象。** return 单例对象*/public static DoubleCheckSingletonSerializable getInstance(){// 第一次检查如果 instance 已经被初始化则直接返回避免不必要的同步开销if(instance null){// 同步类锁保证只有一个线程进入代码块synchronized (DoubleCheckSingletonSerializable.class){// 第二次检查确保只有一个实例被创建if(instance null){// 创建单例对象//潜在的安全问题 线程安全原子性、可见性、顺序性/*1. 分配内存空间2. 初始化对象3. 将 instance 指向分配的内存地址*/instance new DoubleCheckSingletonSerializable();}}}return instance;}public static void main(String[] args) throws Exception {// 正常创建单例对象DoubleCheckSingletonSerializable instance_1 DoubleCheckSingletonSerializable.getInstance();System.out.println(instance_1);//通过序列化和反序列化方式破坏单例ObjectOutputStream oos new ObjectOutputStream(new FileOutputStream(./c.txt));oos.writeObject(instance_1);oos.flush();oos.close();//通过反序列化方式读取ObjectInputStream ois new ObjectInputStream(new FileInputStream(./c.txt));DoubleCheckSingletonSerializable instance_2 (DoubleCheckSingletonSerializable) ois.readObject();ois.close();System.out.println(instance_1 instance_1);System.out.println(instance_2 instance_2);} }返回不同的对象。 instance_1 com.yang.designmode.singleton.DoubleCheckSingletonSerializableeed1f14 instance_2 com.yang.designmode.singleton.DoubleCheckSingletonSerializable4ccabbaa重写readResolve方法 在反序列化时候调用不会创建新的对象返回该方法的对象。 import java.io.*;/*** 双重检查锁定Double-Check Locking实现的单例模式。* 保证了多线程环境下的单例实例创建并且只进行一次同步操作提高性能。*/ public class DoubleCheckSingletonSerializable implements Serializable {/*** 使用 volatile 关键字确保多线程环境下的可见性和禁止指令重排序。* 保证在所有线程中该变量的值是一致的。*/private static volatile DoubleCheckSingletonSerializable instance;/*** 私有构造函数防止外部通过 new 创建实例。*/private DoubleCheckSingletonSerializable(){if(instance!null){//说明有人想要破坏单例特性创建多个实例throw new RuntimeException(DoubleCheckSingletonSerializable.class单例模式不允许创建多个实例);}}/*** 获取单例对象的方法。* 使用双重检查锁定机制来延迟初始化单例对象。** return 单例对象*/public static DoubleCheckSingletonSerializable getInstance(){// 第一次检查如果 instance 已经被初始化则直接返回避免不必要的同步开销if(instance null){// 同步类锁保证只有一个线程进入代码块synchronized (DoubleCheckSingletonSerializable.class){// 第二次检查确保只有一个实例被创建if(instance null){// 创建单例对象//潜在的安全问题 线程安全原子性、可见性、顺序性/*1. 分配内存空间2. 初始化对象3. 将 instance 指向分配的内存地址*/instance new DoubleCheckSingletonSerializable();}}}return instance;}/*** 重写readResolve方法 在反序列化时候调用不会创建新的对象返回该方法的对象* return* throws ObjectStreamException*/public Object readResolve() throws ObjectStreamException {return getInstance();}public static void main(String[] args) throws Exception {// 正常创建单例对象DoubleCheckSingletonSerializable instance_1 DoubleCheckSingletonSerializable.getInstance();System.out.println(instance_1);//通过序列化和反序列化方式破坏单例ObjectOutputStream oos new ObjectOutputStream(new FileOutputStream(./c.txt));oos.writeObject(instance_1);oos.flush();oos.close();//通过反序列化方式读取ObjectInputStream ois new ObjectInputStream(new FileInputStream(./c.txt));DoubleCheckSingletonSerializable instance_2 (DoubleCheckSingletonSerializable) ois.readObject();ois.close();System.out.println(instance_1 instance_1);System.out.println(instance_2 instance_2);} }在DoubleCheckSingletonSerializable.java 中readResolve() 方法返回 getInstance() 和直接返回 instance 的确存区别 返回 getInstance()调用的是单例类的公共静态方法 getInstance()。保证了通过反序列化获取的对象仍然是全局唯一的单例对象。如果将来对 getInstance() 方法做了增强比如增加新的初始化逻辑、日志记录等readResolve() 会自动继承这些行为。更加符合面向对象设计原则避免暴露内部变量。直接返回 instance是对私有静态变量 instance 的直接访问。在当前上下文中虽然也能得到正确的单例对象但跳过了 getInstance() 方法的逻辑。如果未来 getInstance() 方法中增加了额外处理逻辑则不会被触发可能造成不一致的行为。 ✅ 推荐做法使用 return getInstance(); 是更安全和规范的做法。它确保了即使 getInstance() 方法后续发生变化反序列化过程也能保持一致性并遵循单例模式的设计意图。 1.2 单例模式的经典应用 单例模式的经典应用 Spring中的Bean对象默认是单例模式。相关工厂对象都是单例模式如Mybatis中的SqlSessionFactorySpring中的BeanFactory保存相关配置信息的对象如Mybatis中的Configuration对象SpringBoot中的各个xxAutoConfiguration对象。应用程序的日志位置一般都会通过单例实现。数据库连接池的设计 1.3 单例模式的业务实现 适合单例模式的应用场景 配置管理模块保证系统中只有一个配置管理实例可以统一管理系统的配置信息。日志管理模块保证系统中只有一个日志管理实例确保日志记录的一致性和准确性。缓存管理模块保证系统中只有一个缓存管理实例提高系统的性能和效率。数据库连接模块保证系统中只有一个数据库连接池实例避免数据库连接资源的浪费和冲突。 日志管理案例代码 package com.yang.designmode.singleton.business;import java.io.File; import java.io.FileWriter; import java.io.IOException;/*** 日志类 单例模式 饿汉式*/ public class Logger4 {//实现日志的输出private FileWriter fileWriter;private static Logger4 logger4 new Logger4();//实现日志输出private Logger4() {File file new File(./log.txt);try {FileWriter writer new FileWriter(file, true);} catch (IOException e) {throw new RuntimeException(e);}}public static Logger4 getInstance() {return logger4;}/*** 对外输出日志的方法* param message*/public void log(String message) throws IOException {fileWriter.write(message);} } import java.io.IOException;public class OrderController {private Logger1 logger1new Logger1();private Logger4 logger4Logger4.getInstance(); // 饿汉式单例模式public void createOrder(){try {logger1.log(创建订单的处理);logger4.log(创建订单的处理);} catch (IOException e) {e.printStackTrace();}} }1.4 工厂模式 工厂模式帮助我们创建对象不用自己创建即封装对象的创建过程将对象的创建和使用分离减低代码的复杂度。 1.4.1 工厂模式的设计与实现 工厂模式根据需要创建对象的复杂度可以分为简单工厂、工厂方法和抽象工厂。 1.4.2 简单工厂模式 简单工厂模式静态工厂方法可以根据不同的参数返回不同的实例简单工厂模式专门定义一个类来负责创建其他类的实例被创建的实例通常都具有共同的父类。 /*** 工厂模式* 简单工厂模式* 汽车工厂BYD和Audi*/ public class SimpleFactory {public static void main(String[] args) {CarFactory.createCar(Audi).run();CarFactory.createCar(BYD).run();CarFactory.createCar(Benz).run();} } interface Car {void run(); }//定义Car的实现类 class Audi implements Car {Overridepublic void run(){System.out.println(Audi is running...);} }class BYD implements Car {Overridepublic void run(){System.out.println(BYD is running...);} }//创建一个对应的简单工厂类 class CarFactory {//生产汽车的方法public static Car createCar(String type) {if(type.equals(Audi)){return new Audi();}else if(type.equals(BYD)){return new BYD();}throw new RuntimeException(没有这种类型的汽车);} }1.4.3 工厂方法模式 /*** 工厂方法模式*/ public class FactoryMethod {public static void main(String[] args) {CarFactory audiFactory new AudiFactory();Car car audiFactory.createCar();car.run();CarFactory bydFactory new BYDFactory();Car car1 bydFactory.createCar();car1.run();} }interface Car {void run(); }//定义Car的实现类 class Audi implements Car {Overridepublic void run() {System.out.println(Audi is running...);} }class BYD implements Car {Overridepublic void run() {System.out.println(BYD is running...);} }interface CarFactory {Car createCar(); }class AudiFactory implements CarFactory {Overridepublic Car createCar() {return new Audi();} }class BYDFactory implements CarFactory {Overridepublic Car createCar() {return new BYD();} }简单工厂和工厂方法的对比。 简单工厂只有一个工厂而工厂方法有多个工厂。简单工厂不支持拓展而工厂方法支持拓展拓展的方法就是添加对应的工厂类。简单工厂代码复杂度低工厂方法代码复杂度高。 1.4.4 抽象工厂模式 package com.yang.designmode.factory.AbstractFactory;public class AbstractFactory {public static void main(String[] args) {Car car new LuxuryEngineCarFactory().createCar();Engine engine new LuxuryEngineCarFactory().createEngine();car.run();engine.run();}//抽象工厂public static interface AbstractComponentFactory {Car createCar();Engine createEngine();}public static class LuxuryEngineCarFactory implements AbstractComponentFactory {Overridepublic Car createCar() {return new BydCarFactory().createCar();}Overridepublic Engine createEngine() {return new LuxuryEngineFactory().createEngine();}}public static class LowEngineCarFactory implements AbstractComponentFactory {Overridepublic Car createCar() {return new AudiCarFactory().createCar();}Overridepublic Engine createEngine() {return new LowEngineFactory().createEngine();}}//汽车产品族public static interface Car {void run();}public static class Byd implements Car {Overridepublic void run() {System.out.println(比亚迪...);}}public static class Audi implements Car {Overridepublic void run() {System.out.println(奥迪...);}}public static interface CarFactory {Car createCar();}public static class AudiCarFactory implements CarFactory{public Car createCar() {return new Audi();}}public static class BydCarFactory implements CarFactory{public Car createCar() {return new Byd();}}//发动机产品族public static interface EngineFactory {Engine createEngine();}public static interface Engine {void run();}public static class LuxuryEngine implements Engine {Overridepublic void run() {System.out.println( luxury engine...);}}public static class LowEngine implements Engine {Overridepublic void run() {System.out.println( low engine...);}}public static class LuxuryEngineFactory implements EngineFactory{public Engine createEngine() {return new LuxuryEngine();}}public static class LowEngineFactory implements EngineFactory{public Engine createEngine() {return new LowEngine();}}}1.4.5 三者对比 简单工厂模式静态工厂模式虽然某种程度不符合设计原则但实际使用最多。工厂方法模式不修改已有类的前提下通过增加新的工厂类实现拓展。抽象工厂模式不可以增加产品可以增加产品族。 1.4.6 工厂模式的经典应用 Spring框架 BeanFactory和ApplicationContextiSpring的核心接口BeanFastory是一个工厂模式的实现它负责创建和管理应用中的bean。而ApplicationContext是BeanFactory的子接口提供更丰富的功能如国际化支持、事件传播等。FactoryBean.Spring提供FactoryBean接口允许用户定义如何创建对象而不仅仅是简单地通过类的构造器来实例化。 FastoryBean提供了一种更灵活的方式来创建复杂对象。 MyBatis框架: SqlSessionFastoryMyBatis通过SqlsessionFactory来创建SqlSession实例Sqlsession用于执行SQL命令、获取映射器实例和管理事务。SqlSessionFactory是一个工厂类它遵循工厂模式的设计原则。 Hibernate框架: SessionFactory在Hibernate中SessionFactory是一个用于创建Session实例的工厂类。Session是Hibernate中用于执行数据库操作的主要接口而SessionFactory则负责管理Session的创建和配置。 其他框架和API 日志框架如Log4j、SLE4J提供工厂类或方法来创建日志记录器Logger实例。例如在SLF4J中LoggerFactory类用于创建Logger实例。JDBC连接池在JDBC连接池中如Apache Commons DBCP、 C3P0等都使用了工厂模式来管理数据库连接的创建、复用和销毁。依赖注入框架除Spring之外还有其他依赖注入框架如Google Guice 也使用了工厂模式来管理对象的创建和依赖注入。 1.4.7 工厂模式的业务实现 工厂模式的业务实现我们可以根据工厂模式的分类来具体的分析 1.4.7.1 简单工厂模式 应用场景 当需要创建的对象较少且不会频繁增加时可以使用简单工厂模式。客户端只需要知道传入工厂类的参数无需知道具体产品的类名。 业务案例 在一个基于控制台的日志系统中可以根据用户输入的日志级别如INFO、 DEBUG、 ERROR 来创建不同类型的日志记录器 Logger 对象。在一个图形界面应用程序中可以根据用户的选择来创建不同种类的按钮Button对象。 1.4.7.2 工厂方法模式 应用场景 当一个类不知道它所必须创建的对象的类时当一个类希望由它的子类来指定它所创建的对象时当类将创建对象的职责委托给多个帮助子类中的某一个并且你希望将哪一个帮助子类是代理者这一信息局部化时。 业务案例 在一个文档处理系统中可以定义—个Document接口然后为不同类型的文档如Word、PDF、 Text等创建具体的类并分别实现Document接口。同时定义一个PocumentFactory接口并为每种类型的文档创建一个实现了DocumgntFactoy接口的工厂类。在需要创建文档对象时只需调用相应的工厂类即可。 1.4.7.3 抽象工厂模式 应用场景 当一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节时。当这个系统有多于一个的产品族而系统只消费其中某一族的产品时。当同一个产品族中的多个对象被设计在一起工作时它能够保证客户端始终只使用同一个产品族中的对象。 业务案例在一个图形界面库中可能需要创建不同风格的按钮Button和文本框TextField对象。每种风格如Windows风格、Mac风格都包含一套按钮和文本框的类。此时可以使用抽象工厂模式来定义一个抽象工厂接口该接口包含创建按钮和文本框的方法。然后为每种风格创建一个实现了抽象工厂接口的工厂类。在需要创建特定风格的图形界面组件时只需调用相应风格的工厂类即可。 1.5 建造者模式 1.5.1 建造者模式的设计与实现 建造者模式Builder Pattern是一种创建型设计模式用于将一个复杂对象的构建过程与其表示分离使得同样的构建过程可以创建不同的表示。建造者模式适用于需要分步骤构建复杂对象的情况。它通过将构建过程封装在 Director 和 Builder 中实现了高内聚低耦合的设计思想是处理复杂对象创建的理想选择之一。 建造者模式中主要的角色分类 Builder建造者接口定义构建产品各个部分的方法如 buildPartA(), buildPartB() 等。ConcreteBuilder具体建造者实现 Builder 接口提供具体的构建逻辑并返回构建好的产品对象。Director指挥者负责使用 Builder 接口来定义构建的顺序不关心具体实现细节。Product产品角色最终要构建的复杂对象通常由多个部分组成。 1.5.2 适用场景 当一个对象的构建过程复杂且需要多个步骤完成时。同样的构建过程需要产生不同的产品时。需要隔离产品的构造与表示使客户端无需了解内部构建细节。 1.5.3 优缺点 优点 将构建过程和产品表示解耦提高扩展性。更好地控制构建过程便于添加新的建造者类。可以逐步精细地构建对象避免构造函数参数过多的问题。 缺点 增加系统复杂度需要额外定义多个类Builder、ConcreteBuilder、Director。如果产品差异较大可能不适合使用该模式。 1.5.4 代码示例 // Product产品角色 class House {private String foundation;private String walls;private String roof;public void setFoundation(String foundation) {this.foundation foundation;}public void setWalls(String walls) {this.walls walls;}public void setRoof(String roof) {this.roof roof;}Overridepublic String toString() {return House{ foundation foundation \ , walls walls \ , roof roof \ };} }// Builder抽象建造者 interface HouseBuilder {void buildFoundation();void buildWalls();void buildRoof();House getHouse(); }// ConcreteBuilder具体建造者 class ConcreteHouseBuilder implements HouseBuilder {private House house;public ConcreteHouseBuilder() {this.house new House();}Overridepublic void buildFoundation() {house.setFoundation(Concrete Foundation);}Overridepublic void buildWalls() {house.setWalls(Brick Walls);}Overridepublic void buildRoof() {house.setRoof(Tile Roof);}Overridepublic House getHouse() {return house;} }// Director指挥者 class Director {private HouseBuilder builder;public Director(HouseBuilder builder) {this.builder builder;}public void constructHouse() {builder.buildFoundation();builder.buildWalls();builder.buildRoof();} }// 测试类 public class Client {public static void main(String[] args) {HouseBuilder builder new ConcreteHouseBuilder();Director director new Director(builder);director.constructHouse();House house builder.getHouse();System.out.println(house.toString());} }输出结果 House{foundationConcrete Foundation, wallsBrick Walls, roofTile Roof}1.5.5 建造者模式经典应用 Guava中的缓存处理。MyBatis中的SqlSessionFactoryBuilder的处理。MyBatis中的MappedStatement的创建。 1.5.6 建造者模式和工厂模式的区别 建造者模式和工厂模式都可以创建对象它们创建对象的关注点不一样。工厂模式用来创建类型不同但有相关的对象继承同一个父类或接口的一组子类通过参数来决定创建哪种类型的对象。建造者模式用来创建同一种类型复杂对象通过设置不同的可选参数来定制化创建不同的对象。现实案例去餐厅吃饭 工厂模式炒饭火锅炒菜……建造车模式火锅【不同的口味麻辣、香辣、清淡……】 1.6 原型模式 1.6.1 原型模式的设计与实现 原型模式克隆模式以一个对象为原型克隆出一个一模一样的对象该对象的属性和原型对象一样。而且对原型对象没有任何影响。它的主要目的是通过已有的对象来创建新对象而无需调用构造函数。核心思想原型模式的核心在于clone()方法的使用它允许你通过复制一个已有对象来创建新的对象实例。这在创建对象的成本较大时非常有用。原型模式的克隆模式分为两种浅克隆浅拷贝和深克隆深拷贝。 原型模式说明浅克隆浅拷贝只复制基本数据类型的值对引用类型只复制引用地址深克隆深拷贝递归复制所有关联的对象确保完全独立 应用场景 当系统需要动态加载类或者避免通过工厂方法频繁创建对象时。创建对象成本较高时如数据库连接、大对象初始化等。需要保证对象之间的隔离性例如撤销/重做功能。 1.6.2 浅克隆方式 被复制对象的所有变量都含有与原来对象相同的值所有对其他对象的引用仍然指向原来的对象。换句话说浅复制只复制所考虑对象不复制它所引用的对象。Object类提供的方法clone只拷贝本对象对象内部的数组和引用对象都不拷贝仍然指向原生对象的内部元素地址。被克隆对象必须实现cloneable、Serializable接口。 package com.yang.designmode.prototype;import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Date;public class UserShallowType implements Cloneable {private String name;private int age;private Date birthday;public UserShallowType() {}public UserShallowType(String name, int age, Date birthday) {this.name name;this.age age;this.birthday birthday;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday birthday;}public String toString() {return User [name name , age age , birthday birthday ];}Overridepublic UserShallowType clone() {try {UserShallowType clone (UserShallowType) super.clone();// TODO: 复制此处的可变状态这样此克隆就不能更改初始克隆的内部项return clone;} catch (CloneNotSupportedException e) {throw new AssertionError();}}public static void main(String[] args) {UserShallowType user new UserShallowType();user.setName(yang);user.setAge(18);LocalDate localDate LocalDate.parse(2000-01-01, DateTimeFormatter.ISO_LOCAL_DATE);user.setBirthday(java.sql.Date.valueOf(localDate));UserShallowType user1 user.clone();user1.setName(yang1);System.out.println(源对象 user);System.out.println(浅克隆对象 user1);// 验证共享 birthday 的行为Date userBirthday user.getBirthday();userBirthday.setTime(userBirthday.getTime() 1000 * 60 * 60 * 24 * 1); // 加一天System.out.println(验证共享 birthday 的行为);System.out.println(源对象 user);System.out.println(浅克隆对象 user1);} }源对象User [nameyang, age18, birthday2000-01-01] 浅克隆对象User [nameyang1, age18, birthday2000-01-01] 验证共享 birthday 的行为 源对象User [nameyang, age18, birthday2000-01-02] 浅克隆对象User [nameyang1, age18, birthday2000-01-02]浅克隆的问题只复制基本数据类型的值对引用类型只复制引用地址。 1.6.3 深克隆方式 package com.yang.designmode.prototype;import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Date;public class UserDeepType implements Cloneable {private String name;private int age;private Date birthday;public UserDeepType() {}public UserDeepType(String name, int age, Date birthday) {this.name name;this.age age;this.birthday birthday;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday birthday;}public String toString() {return User [name name , age age , birthday birthday ];}Overridepublic UserDeepType clone() {try {UserDeepType clone (UserDeepType) super.clone();// 实现克隆对象属性的深拷贝clone.birthday (Date) clone.birthday.clone();return clone;} catch (CloneNotSupportedException e) {throw new AssertionError();}}public static void main(String[] args) {UserDeepType user new UserDeepType();user.setName(yang);user.setAge(18);LocalDate localDate LocalDate.parse(2000-01-01, DateTimeFormatter.ISO_LOCAL_DATE);user.setBirthday(java.sql.Date.valueOf(localDate));UserDeepType user1 user.clone();user1.setName(yang1);System.out.println(源对象 user);System.out.println(深克隆对象 user1);// 验证不共享 birthday 的行为Date userBirthday user.getBirthday();userBirthday.setTime(userBirthday.getTime() 1000 * 60 * 60 * 24 * 1); // 加一天System.out.println(验证不共享 birthday 的行为);System.out.println(源对象 user);System.out.println(深克隆对象 user1);} }源对象User [nameyang, age18, birthday2000-01-01] 深克隆对象User [nameyang1, age18, birthday2000-01-01] 验证共享 birthday 的行为 源对象User [nameyang, age18, birthday2000-01-02] 深克隆对象User [nameyang1, age18, birthday2000-01-01]1.6.4 序列化方式深克隆 在对象引用关系复杂的情况下使用 clone() 方法实现深拷贝会变得非常繁琐尤其是当对象中包含嵌套引用、循环引用或多层结构时。此时通过序列化和反序列化的方式进行深拷贝是一种更为通用和稳定的解决方案。 1.6.4.1 序列化深拷贝的原理 将对象 序列化为字节流或 JSON 字符串等然后再 反序列化为新对象。因为整个过程是“从无到有”的重建所以新的对象与原对象完全独立实现了真正的深拷贝。 1.6.4.2 适用前提 对象及其所有引用的对象都必须实现 Serializable 接口如果是 Java 原生序列化。避免使用 transient 关键字修饰需要拷贝的字段。 1.4.6.3 以 Java 原生序列化为例 package com.yang.designmode.prototype;import java.io.*; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Date;public class UserDeepTypeSerializable implements Cloneable,Serializable {private String name;private int age;private Date birthday;public UserDeepTypeSerializable() {}public UserDeepTypeSerializable(String name, int age, Date birthday) {this.name name;this.age age;this.birthday birthday;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday birthday;}public String toString() {return User [name name , age age , birthday birthday ];}Overridepublic UserDeepTypeSerializable clone() {try {UserDeepTypeSerializable clone (UserDeepTypeSerializable) super.clone();// 实现克隆对象属性的深拷贝clone.birthday (Date) clone.birthday.clone();return clone;} catch (CloneNotSupportedException e) {throw new AssertionError();}}public static void main(String[] args) throws Exception {UserDeepTypeSerializable user new UserDeepTypeSerializable();user.setName(yang);user.setAge(18);LocalDate localDate LocalDate.parse(2000-01-01, DateTimeFormatter.ISO_LOCAL_DATE);user.setBirthday(java.sql.Date.valueOf(localDate));System.out.println(源对象 user);//序列化ByteArrayOutputStream bos new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(bos);oos.writeObject(user);//反序列化ByteArrayInputStream bis new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois new ObjectInputStream(bis);UserDeepTypeSerializable user_1 (UserDeepTypeSerializable)ois.readObject();System.out.println(序列化深克隆对象user_1);// 验证不共享 birthday 的行为Date userBirthday user.getBirthday();userBirthday.setTime(userBirthday.getTime() 1000 * 60 * 60 * 24 * 1); // 加一天System.out.println(验证不共享 birthday 的行为);System.out.println(源对象 user);System.out.println(深克隆对象 user_1);} }源对象User [nameyang, age18, birthday2000-01-01] 序列化深克隆对象User [nameyang, age18, birthday2000-01-01] 验证不共享 birthday 的行为 源对象User [nameyang, age18, birthday2000-01-02] 深克隆对象User [nameyang, age18, birthday2000-01-01]1.4.6.4 复杂引用关系的深拷贝 // 定义类结构 import java.io.Serializable;class Address implements Serializable {private String city;private String street;public Address(String city, String street) {this.city city;this.street street;}// Getter Setter }class User implements Serializable {private String name;private Address address;public User(String name, Address address) {this.name name;this.address address;}// Getter Setter }// 使用深拷贝工具 public class Client {public static void main(String[] args) {Address address new Address(Beijing, Chaoyang Road);User user new User(Alice, address);User clonedUser DeepCopyUtil.deepCopy(user);// 修改原对象属性user.getAddress().setCity(Shanghai);System.out.println(clonedUser.getAddress().getCity()); // 输出: Beijing未受影响} }1.4.6.5 其他序列化方案对比 方案特点适用场景Java 原生序列化简单但性能较差需实现 Serializable快速原型、调试JSON 序列化如 Jackson、Gson可读性好兼容性强Web 服务、跨语言交互Kryo / Hessian / Protobuf高性能二进制序列化大数据、高性能要求系统 1.6.5 原型模式的经典应用 原型模式在Spring中主要体现在Bean的作用域管理上。Spring默认以单例模式Singleton Scope创建和管理Bean但它也支持原型作用域 Prototype Scope。当Bean的作用域被设置为prototype时Spring容器会对每次的getBean()请求都创建一个新的Bean实例而不是返回同一个共享的实例。在需要每次请求都拥有独立对象实例的场景中非常有用比如处理用户会话或请求时。Apache Commons Lang库中的SerializationUtils方法也实现了原型模式通过序列化和反序列化的方式实现对象的深拷贝。这种方法可以处理复杂的对象图包括那些含有循环引用的对象。 在下面这些场景中可以考虑使用原型模式 高成本对象的创建当对象的创建成本较高例如涉及复杂的初始化过程、大量数据的加载或昂贵的I/O操作时使用原型模式可以避免重复的创建过程通过复制现有对象来快速生成新对象从而提高性能。减少初始化时间通过复制一个已经初始化的实例可以快速生成新的实例减少了初始化所需的时间。相似对象的创建当系统中存在大量相似的对象且对象之间的差异主要在于少数几个属性时可以使用原型模式来复制基础对象并根据需要修改这些属性从而快速生成大量相似但不完全相同的对象。图形界面组件在图形用户界面中复杂的组件如表格、树等可能需要从磁盘或数据库加载大量数据。使用原型模式可以快速复制已有的组件实例而无需重新加载数据。数据库连接池数据库连接的创建和销毁成本较高使用原型模式可以重用现有的连接对象减少连接建立和关闭的开销。对象缓存对于需要频繁访问但创建成本较高的对象可以将其缓存起来并在需要时通过复制缓存中的对象来快速获取新对象从而减少创建新对象的次数。灵活配置在复制过程中可以对对象进行动态修改以适应不同的使用场景或配置需求。这种灵活性使得原型模式在需要动态生成不同状态对象时非常有用。复杂构造函数当对象的构造函数过于复杂或者存在多个构造函数时原型模式提供一种更灵活的创建方式。通过复制一个已经配置好的对象可以避免调用复杂的构造函数。对象间的依赖在某些情况下对象的创建可能依赖于其他多个对象的状态或配置。使用原型模式可以简化依赖关系通过复制正确配置的对象来快速生成新对象。 1.6.6 原型模式的业务实现 在电商系统中为统计用户的喜好和当时的热点方向。在数据库中存储大约30万条所有关键词信息帮助分析用户喜好为决策提供支持搜索关键信息包括关键词搜索次数和时间戳等信息。系统A会把检索数据加载到内存中提高查询效率存储在HashMap中系统B会间隔统计分析搜索日志信息并更新到数据库中。 import java.io.*; import java.util.HashMap; import java.util.List;/*** 系统A要同步数据中的统计发数据* 保证数据的一致性*/ public class ProtoType {//记录缓存 检索统计数据private HashMapString, SearchWord currentKeyWords new HashMap();private long lastUpdateTime -1;/*** 系统A需要调用同步的方法* 1. 根据时间戳查询出对应的统计数据* 2. 遍历每条统计数据* 3. 比较已经缓存的数据存在就替换不存在就删除* 存在的问题更新的时刻无法保证一致性*/public void refresh() throws Exception {//记录新的数据HashMapString, SearchWord newKeyWords (HashMapString, SearchWord) deeppClone(currentKeyWords);// 根据时间戳查询出对应的记录信息ListSearchWord list getSearchWords(lastUpdateTime);long maxNewUpdateTime lastUpdateTime;if(list!null){// 遍历每条统计数据for (SearchWord data : list) {if(data.getLastUpdateTime()maxNewUpdateTime){maxNewUpdateTime data.getLastUpdateTime();}if (newKeyWords.containsKey(data.getKeyWord())) {newKeyWords.replace(data.getKeyWord(), data);} else {newKeyWords.put(data.getKeyWord(), data);}}lastUpdateTimemaxNewUpdateTime;currentKeyWords newKeyWords;}}private ListSearchWord getSearchWords(long lastUpdateTime){return null;}public Object deeppClone(Object obj) throws Exception {ByteArrayOutputStream bos new ByteArrayOutputStream();ObjectOutputStream oos new ObjectOutputStream(bos);oos.writeObject(obj);ByteArrayInputStream bis new ByteArrayInputStream(bos.toByteArray());ObjectInputStream ois new ObjectInputStream(bis);return ois.readObject();} }
http://www.dnsts.com.cn/news/49458.html

相关文章:

  • 阿里做网站怎么做济南公司做网站的价格
  • 俄语网站推广个人网站代做
  • 站长查询域名秦皇岛app开发公司
  • 绿色科技网站建设工作证明怎么写
  • 网站提升排名高端网站建设策划
  • 哪家能建设网站企业服务账号是什么
  • 灰色风格的网站企业网站seo推广
  • 织梦网站模板修改wordpress类开源网站
  • 推广网站最有效方法学硬件好还是学软件好
  • 河源市住房和城乡建设局网站东营造价信息网官网
  • 青岛公司网站设计网易企业邮箱修改密码
  • 好看的网站模板哪个网站做婚礼邀请函好
  • 手机网站弹出提示框主题巴巴WordPress主题后门
  • 广告推广平台网站有哪些免费工程信息网
  • 那个旅游网站可以做行程西安企业建站公司
  • 仿笑话网站源码云南楚雄医药高等专科学校
  • 潍坊网站建设优化微信公众号制作方法
  • 360网站点评基于php的网站开发设计
  • 淘宝seo是指什么哈尔滨优化seo外包公司
  • 咸阳网站制作网站制作容易吗怎么样
  • 微网站开发程序wordpress搜索提示
  • sae网站开发企业网站建设算什么费用
  • 生活服务网站开发与设计wordpress 星 评分
  • 怎么快速做网站文章wordpress 女性主题
  • 没有网站的域名寄生虫做网站流量
  • 做洗衣液的企业网站网站建设重点
  • 柳市做网站制作wordpress访问多站点
  • 关于大创做网站的项目计划书如何做网站后台
  • 潍坊高端网站建设服装网页设计模板图片
  • 网站排名优化推广厦门沈阳哪个公司可以做网站