6做网站,wordpress 地址设置方法,做网站首页需要什么资料,禅城网站建设文章目录 设计模式设计模式分类UML类图设计模式的原则 常用设计模式创建型设计模式单例设计模式饿汉模式懒汉模式#xff08;线程不安全#xff09;懒汉模式#xff08;线程安全#xff09;- Synchronized懒汉模式#xff08;线程安全#xff09;- Double Check懒汉模式线程不安全懒汉模式线程安全- Synchronized懒汉模式线程安全- Double Check懒汉模式线程安全- 静态内部类枚举总结 工厂设计模式简单工厂模式工厂方法模式抽象工厂模式 建造者设计模式Builder 结构型设计模式代理设计模式Proxy静态代理动态代理 行为型设计模式责任链 设计模式
设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式代表了最佳的实践通常被有经验的软件开发人员所使用。
借助于设计模式可以编写出非常高效的代码可复用性以及稳健性都会比较强有助于阅读源码框架 设计模式分类
GoF4人组设计模式共有23种根据用途的不同设计模式可以分为创建型、结构型、行为型三种。
创建型模式 由无到有的设计模式是为了创建应用程序的实例例如单例模式、工厂模式、建造者模式 结构型模式 在已有的实例的基础上做了一些额外的事情例如代理模式 行为型模式 多个类或者实例存在的一定的关系例如责任链模式 UML类图
UML全称Unified Modeling Language是用来进行软件设计的可视化建模工具。
见知乎链接https://zhuanlan.zhihu.com/p/109655171
eg
public class UserService {private String username;public String password;Integer age;public void sayUsername(String username) {}public String bye(String name1, Integer days) {return null;}
}设计模式的原则
设计原则按照字母手写简写可以概括为SOLID原则。
单一职责原则Single Responsibility Principle 让每个类的功能单一 尽量使得每个类只负责整个软件的功能模块中的一个 开放封闭原则Open Close Principle 对新增开发对修改封闭已有的代码直接进行修改是有很大风险的如果有新需求可以在已有的代码进行进一步扩展 里氏替换原则Liskov Substitution Principle 凡是父类出现的地方都可以替换为其子类子类继承父类尽量不要重写父类的方法eg 迪米特法则Least Knowledge Principle 又叫作最少知道原则指的是一个类/模块对于其他的类/模块有越少的了解越好 接口分离原则Interface Segregation Principle 不要写大接口大接口中的方法多否则会给实现类带来负担 依赖倒置原则Dependency Inversion Principle 开发过程中先开发接口在开发实现类 具体实现类抽象类的子类抽象接口和抽象类 常用设计模式 创建型设计模式
单例设计模式
保证一个类只有一个实例对象并提供了一个访问该实例对象的全局节点eg在整个应用程序中如果要获得MySingleton实例始终获得的都是同一个单例设计模式分为懒汉模式懒加载和饿汉模式立即加载 懒加载使用的时候才获得实例立即加载使用之前已经获得实例 单例设计模式的设计原则 构造方法私有 定义一个成员变量私有静态的成员变量用来接收私有构造方法构造的实例 提供一个静态方法供外部类调用这个实例
饿汉模式
特点不支持延时加载懒加载获取对象速度比较快但是如果对象比较大或者一直没有去使用那么比较浪费内存空间。
// 单例设计模式在整个应用程序中如果要获得MySingleton实例始终获得的都是同一个
// 单例手写是面试过程中常见的问题/** 1. 构造方法私有* 2. 定义一个成员变量私有静态的成员变量用来接收私有构造方法构造的实例* 3. 提供一个静态方法供外部类调用这个实例*/
public class MySingleton {// new MySingleton();// 定义了一个实例要初始化这个实例// final是不让你去额外修饰它private static final MySingleton instance new MySingleton();private MySingleton(){}// 调用getInstance方法之前已经完成了实例化public static MySingleton getInstance(){return instance;}
}
懒汉模式线程不安全
/*** 懒加载线程不安全在完成instance null这句判断之后做了线程的切换导致线程不安全*/
public class MySingleton2 {private static MySingleton2 instance;private MySingleton2() {}public static MySingleton2 getInstance() {// 第一次使用getInstance方法的时候初始化instance// 如何识别是不是第一次使用instance// 第一次使用instance的时候是nullif (instance null) {instance new MySingleton2();}return instance;}
}
懒汉模式线程安全- Synchronized
效率低 因为执行这个方法需要排队
public class MySingleton3 {private static MySingleton3 instance;private MySingleton3() {}// 使用synchornized关键字即可public static synchronized MySingleton3 getInstance() {if(instance null){instance new MySingleton3();}return instance;}
}懒汉模式线程安全- Double Check
public class MySingleton4 {private static MySingleton4 instance;private MySingleton4() {}public static MySingleton4 getInstance() {// double check做了两次非空的判断if (instance null) {synchronized (MySingleton4.class) {// 如果这里的instance null不判断的话仍然有线程切换导致创建多次实例的风险if (instance null) {instance new MySingleton4();}}}return instance;}
}
懒汉模式线程安全- 静态内部类
静态内部类的静态代码块的加载时机使用静态内部类的时候才执行里面的静态代码块 可以把实例化的这部分代码放到静态代码块的内部中
/*** 懒汉模式静态内部类的方式进行加载* 静态代码块中的内容只会执行一次所以是线程安全的*/
public class MySingleton5 {private MySingleton5() {}static class Inner {private static MySingleton5 instance;static {instance new MySingleton5();}private static MySingleton5 getInstance() {return instance;}}// 使用该方法才会触发静态内部类的静态代码块的初始化 - 懒加载public static MySingleton5 getInstance() {return Inner.getInstance();}
}
枚举
public enum Singleton6 {INSTANCE;public static Singleton6 getInstance(){return INSTANCE;}
}总结
饿汉式在类加载时期便已经将instance实例对象创建了所以这种方式是线程安全的方式但是不支持懒加载。懒汉式该种方式支持懒加载但是要么不是线程安全要么虽然是线程安全但是需要频繁释放锁、抢夺锁并发量较低。双重检查既可以实现懒加载又可以实现高并发的需求。这种方式比较完美但是代码有一些复杂。静态内部类使用该种方式也可以解决懒加载以及高并发的问题代码实现起来比双重检查也是比较简洁。枚举最简单、最完美的实现方式。 工厂设计模式
工厂中一定会提供一个返回实例的方法。其中核心的好处是封装隐藏生产的具体细节工厂类或接口的命名方式通常为XXXFactory
简单工厂模式
只要一个工厂函数就可以了那么只需要传入不同的参数就可以返回不同的产品实例这种模式就叫简单工厂模式。未满足开闭原则
eg
public class SimpleFactoryExecution {public static void main(String[] args) {// 非简单工厂模式withoutFactory();// 简单工厂模式withFactory();}private static void withFactory() {Scanner scanner new Scanner(System.in);String s scanner.nextLine();SimpleAodiFactory simpleAodiFactory new SimpleAodiFactory();Aodi aodi simpleAodiFactory.create(s);aodi.run();}private static void withoutFactory() {
// Aodi aodi new A4();
// aodi.run();Scanner scanner new Scanner(System.in);String s scanner.nextLine();Aodi aodi null;// 下面这部分属于生产的细节要把生产细节隐藏起来if(A4.equals(s)){aodi new A4();}else if(A5.equals(s)){aodi new A5();}else{aodi new Q5();}aodi.run();}
}public class SimpleAodiFactory {// static 增不增加都是可以的public Aodi create(String s){Aodi aodi null;if(A4.equals(s)){aodi new A4();}else if(A5.equals(s)){aodi new A5();}else{aodi new Q5();}return aodi;}
}
工厂方法模式
核心思想创建工厂接口增加不同的实现类之后它里面的工厂方法就是不用的实现要求把工厂定义为接口或抽象类通过不同的实现类实现不同实例的生产 FactoryBean
eg
// 接口类
public interface AodiFactory {public Aodi create();
}public class A4Factory implements AodiFactory{Overridepublic Aodi create() {return new A4();}
}public class FactoryMethodExecution {public static void main(String[] args) {AodiFactory aodiFactory new A4Factory();aodiFactory.create();}
}抽象工厂模式
抽象工厂生产的一系列的产品上面两种工厂模式生产的产品比较单一
eg 建造者设计模式Builder
开发过程中会遇到这样一个场景它的名字不叫XXXBuilder但是它是采用建造者设计模式的思想来完成egStringBuilder是建造者设计模式建造者模式也叫作生成器模式就是分步骤创建复杂对象建造者设计模式的代码风格 首先要创建要生产的实例仅仅是执行了构造方法 会提供很多设置属性值的方法 会提供返回实例的方法方法名通常是build
eg
Data
public class Phone {private String battery;private String screen;private String os;private String camera;private String color;// 通过Data提供了getter/setter方法以及我们打印的时候用的toString方法
}public class PhoneBuilder {// 当我创建PhoneBuilder实例的时候同时会创建一个Phone的实例// 定义一个全局变量意味着使用一个Builder实例的方法其实对同一个Phone做参数设置private Phone phone new Phone();public PhoneBuilder color(String color) {this.phone.setColor(color);return this;}public PhoneBuilder battery(String battery) {this.phone.setBattery(battery);return this;}public PhoneBuilder screen(String screen) {this.phone.setScreen(screen);return this;}public PhoneBuilder os(String os) {this.phone.setOs(os);return this;}public PhoneBuilder camera(String camera) {this.phone.setCamera(camera);return this;}// 返回实例的方法// 虽然这个方法叫建造但其实在创建Builder实例的时候要建造的实例已经实例化了public Phone build() {return this.phone;}
}// 使用
public class UseBuilder {public static void main(String[] args) {PhoneBuilder builder new PhoneBuilder();// 方法的连续调用Phone phone builder.battery(4000mha).camera(1080P).color(尊贵黑).screen(4K高清).os(Android).build();System.out.println(phone phone);}
}eg参考StringBuilder的代码风格private static void builder1() {StringBuilder sb new StringBuilder();sb.append(hello).append( world).append(!);String s sb.toString();System.out.println(s);}结构型设计模式
代理设计模式Proxy
增强满足基本的需求之外还做了额外的事情通用的事情核心特点 代理类存在和委托类一样的方法这个一样指的是外观上 代理类执行方法的过程中一定会执行委托类的方法 代理模式最大的优点 可以不更改目标类代码的前提下扩展目标类代码的功能。
静态代理
委托类、目标类targetUserServiceImpl代理类UserServiceProxy要保证代理类和委托类提供的方法的外观完全一样 实现和委托类相同的接口 继承委托类重写委托类中的方法 代理类中要调用委托类的方法静态代理最大的缺点 代码较为冗余每代理一个类便要手动编写一个代理类代理对象和目标类对象均实现了接口如果接口发生了修改不仅目标类需要更改代理类也需要同步发生修改维护成本变高了很多
eg
public interface UserService {public int insert(String name);public int remove(int id);
}public class UserServiceImpl implements UserService{Overridepublic int insert(String name) {System.out.println(执行UserServiceImpl的insert方法);return 0;}Overridepublic int remove(int id) {System.out.println(执行UserServiceImpl的remove方法);return 0;}
}// 方法1代理类实现了和委托类相同的接口
public class UserServiceProxy implements UserService{private UserService userService new UserServiceImpl();Overridepublic int insert(String name) {// 应该执行UserServiceImpl的insert方法int insert userService.insert(name);return insert;}Overridepublic int remove(int id) {// 应该执行UserServiceImpl的remove方法int remove userService.remove(id);return remove;}
}// 方法2代理类继承了委托类
public class UserServiceProxy1 extends UserServiceImpl{Overridepublic int insert(String name) {// 调用父类的方法 - 调用了委托类的方法return super.insert(name);}Overridepublic int remove(int id) {return super.remove(id);}
}public class Execution {public static void main(String[] args) {withoutProxy();withProxy();}private static void withProxy() {// 1. 获得代理对象UserService userService new UserServiceProxy();// 2. 使用代理对象调用方法它的外观跟委托类是一模一样的userService.insert(1);}private static void withoutProxy() {UserServiceImpl userService new UserServiceImpl();userService.insert(1);}
}动态代理
静态代理的代理类需要自己手动去写动态代理的代理类不用自己手动去写分类 JDK动态代理 会自动生成代理类与UserServiceProxy类似代理类和委托类实现了相同的接口效率比较高委托类必须实现接口 cglib动态代理 会自动生成代理类与UserServiceProxy1类似代理类继承自委托类委托类可以不实现接口 JDK动态代理
JDK动态代理即JDK给我们提供的动态生成代理类的方式无需引入第三方jar包但是使用JDK动态代理有一个先决条件那就是目标类对象必须实现了某个接口如果目标类对象没有实现任何接口则JDK动态代理无法使用。生成的代理类中的所有的方法都会指向同一个方法InvocationHandler的invoke方法需要程序员来实现InvocationHandler可以直接写实现类、也可以使用匿名内部类的invoke方法
eg
public interface UserService {public String sayHello(String name);
}public class UserServiceImpl implements UserService{Overridepublic String sayHello(String name) {String result hello name;System.out.println(result);return result;}
}Data
public class ProxyGenerator {// 目标类委托类对象Object target;// 返回代理对象public Object generator() {// JDK动态代理的代理对象生成// 新增一个代理的对象/*** Proxy.newProxyInstance( 1 , 2 , 3);* 1. 类加载器* 2. 委托类接口的数组* 3. InvocationHandler 指导代理对象中的方法做何种增强* 返回值代理对象*/UserService proxy (UserService) Proxy.newProxyInstance(ProxyGenerator.class.getClassLoader(),UserServiceImpl.class.getInterfaces(), new CustomInvocationHandle(target));proxy.sayHello(zs);return proxy;}// 匿名内部类实现public Object generator2() {UserService proxy (UserService) Proxy.newProxyInstance(ProxyGenerator.class.getClassLoader(),UserServiceImpl.class.getInterfaces(), new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object invoke method.invoke(target, args);return invoke;}});return proxy;}
}AllArgsConstructor
NoArgsConstructor
public class CustomInvocationHandle implements InvocationHandler {Object instance;Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(开启事务);Object invoke method.invoke(instance, args);System.out.println(关闭事务);return invoke;}
}public class JdkProxyExecution {public static void main(String[] args) {UserService userService new UserServiceImpl();ProxyGenerator proxyGenerator new ProxyGenerator();proxyGenerator.setTarget(userService);UserService proxy (UserService) proxyGenerator.generator();UserService proxy2 (UserService) proxyGenerator.generator2();proxy.sayHello(zs);}
}开启事务
hello zs
关闭事务
开启事务
hello zs
关闭事务cglib动态代理
生成的代理类中的所有的方法都会指向同一个方法InvocationHandler的invoke方法需要程序员来实现InvocationHandler可以直接写实现类、也可以使用匿名内部类的invoke方法主要原因在于Cglib扩展的代理类会继承自目标类。所以这也要求我们的目标类不能是final修饰。
eg
AllArgsConstructor
NoArgsConstructor
Data
public class CglibProxyGenerator {Object target;public Object generator(){// 第一个参数传委托类的classObject proxy Enhancer.create(UserServiceImpl.class, new InvocationHandler() {Overridepublic Object invoke(Object o, Method method, Object[] objects) throws Throwable {System.out.println(开始事务);Object invoke method.invoke(target, objects);System.out.println(结束事务);return invoke;}});return proxy;}
}public class CglibProxyExecution {public static void main(String[] args) {CglibProxyGenerator generator new CglibProxyGenerator();generator.setTarget(new UserServiceImpl());UserService proxy (UserService) generator.generator();proxy.sayHello(zs);}
}开始事务
hello zs
结束事务动态代理小结
代理类中一定会包含和委托类外观一致的方法该方法中一定会有委托类方法的调用 静态代理instance、super调用动态代理method.invoke JDK动态代理的委托类一定要实现接口JDK代理对象只能使用接口来接收猫不能接收狗 代理类实现了和委托类相同的接口 Cglib动态代理接口和实现类都可以接收 代理类继承委托类 使用动态代理所有的方法都会指向InvocationHandler的invoke方法 真正需要程序员开发的内容提供InvocationHandler的实现类定义实现类或匿名内部类实现其中的invoke方法 动态代理的优势在于实现方法的通用的增强把委托类中出现的相同的内容给提取出来
面试问题代理类和委托类之间的关系是什么 分JDK动态代理和Cglib动态代理两方面回答 行为型设计模式
责任链
责任链是一种行为设计模式允许请求沿着链进行发送。收到请求后每个处理者均可对请求进行处理或者将其传递给链上的下一个处理者。
eg
将一些共性的部分放置在一个基类中其中提供的成员变量next能够维护顺序关系通过调用其提供的setNext方法完成顺序关系的维护handle方法能够提供不同的
Data
public abstract class AbstractHandler {AbstractHandler next;public void handle(){handleCore();if (next ! null) {next.handle();}}protected abstract void handleCore();
}/*** 1. 包含处理方法* 2. 执行完当前处理方法要执行下一个处理器的处理方法* 3. 内部可以通过成员变量指向下一个处理器*/
Data
public class Handler1 extends AbstractHandler {//AbstractHandler next;/*public void handle(){handleCore();if (next ! null) {next.handle();}}*/public void handleCore() {System.out.println(Handler1的handle);}
}Data
public class Handler2 extends AbstractHandler {//AbstractHandler next;/*public void handle(){handleCore();if (next ! null) {next.handle();}}*/public void handleCore() {System.out.println(Handler2的handle);}
}Data
public class Handler3 extends AbstractHandler {//AbstractHandler next;/*public void handle(){handleCore();if (next ! null) {next.handle();}}*/public void handleCore() {System.out.println(Handler3的handle);}
}public class ChainExecution {public static void main(String[] args) {Handler1 handler1 new Handler1();Handler2 handler2 new Handler2();Handler3 handler3 new Handler3();Handler4 handler4 new Handler4();handler1.setNext(handler2);handler2.setNext(handler3);handler3.setNext(handler4);// handler1 - handler2 - handler3// handler1.handle - handler2.handle - handler3.handlehandler1.handle();}小结
责任链模式降低了系统之间的耦合性提升了系统的可扩展性。在很多中间件、框架的内部大量地使用了该种设计模式比如Filter的执行过程等。