本专栏将从基础开始,循序渐进,由浅入深讲解常见的设计模式,希望大家都能够从中有所收获,也请大家多多支持。
专栏地址:设计模式实战
所有代码地址:代码地址
如果文章知识点有错误的地方,请指正!大家一起学习,一起进步。
文章目录
1 原型模式
1.1 使用序列化深拷贝
import lombok.Data;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
//深拷贝对象,super.clone()方法是浅拷贝
@Data
public class ConcretePrototype implements Cloneable, Serializable {
private int age;
private String name;
private List<String> hobbies;
//浅拷贝
@Override
protected ConcretePrototype clone() throws CloneNotSupportedException {
try{
return (ConcretePrototype)super.clone();
}catch (Exception e){
e.printStackTrace();
return null;
}
}
//深拷贝
public ConcretePrototype deepClone(){
try{
//字节输出流
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//对象输出流
ObjectOutputStream objectOutput = new ObjectOutputStream(byteArrayOutputStream);
//写入对象
objectOutput.writeObject(this);
//字节输入流
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
//对象输入流
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
//读入对象
return (ConcretePrototype)objectInputStream.readObject();
}catch (Exception e){
e.printStackTrace();
return null;
}
}
@Override
public String toString() {
return "ConcretePrototype{" +
"age=" + age +
", name='" + name + '\'' +
", hobbies=" + hobbies +
'}';
}
public static void main(String[] args) {
//创建原型对象
ConcretePrototype concretePrototype = new ConcretePrototype();
concretePrototype.setAge(18);
concretePrototype.setName("Tom");
List<String> hobbies = new ArrayList<String>();
hobbies.add("书法");
hobbies.add("美术");
concretePrototype.setHobbies(hobbies);
System.out.println(concretePrototype);
//等号赋值传递的是引用
hobbies.add("美术");
System.out.println(concretePrototype);
try{
ConcretePrototype concretePrototype1 = concretePrototype.clone();
concretePrototype1.getHobbies().add("英语");
System.out.println(concretePrototype);
System.out.println(concretePrototype1);
ConcretePrototype concretePrototype2 = concretePrototype.deepClone();
concretePrototype2.getHobbies().add("数学");
System.out.println(concretePrototype);
System.out.println(concretePrototype2);
}catch (Exception e){
e.printStackTrace();
}
}
}
2 建造者模式
2.1 简单建造者
- Course.java
import lombok.Data;
@Data
public class Course {
private String name;
private String PPT;
private String video;
private String note;
private String homework;
}
- CourseBuilder.java
public class CourseBuilder {
private Course course = new Course();
public CourseBuilder addName(String name){
course.setName(name);
return this;
}
public CourseBuilder addPPT(String PPT){
course.setPPT(PPT);
return this;
}
public CourseBuilder addVideo(String video){
course.setVideo(video);
return this;
}
public CourseBuilder addNote(String note){
course.setNote(note);
return this;
}
public CourseBuilder addHomework(String homework){
course.setHomework(homework);
return this;
}
public Course build(){
return course;
}
public static void main(String[] args) {
CourseBuilder builder = new CourseBuilder().addName("设计模式").addPPT("PPT课件").addVideo("回放视频").addNote("课堂笔记").addHomework("课后作业");
System.out.println(builder.build());
}
}
2.2 内部类建造者
import lombok.Data;
@Data
public class CourseInnerBuilder {
private String name;
private String PPT;
private String video;
private String note;
private String homework;
public static class Builder{
private CourseInnerBuilder course = new CourseInnerBuilder();
Builder(){
}
public Builder addName(String name){
course.setName(name);
return this;
}
public Builder addPPT(String PPT){
course.setPPT(PPT);
return this;
}
public Builder addVideo(String video){
course.setVideo(video);
return this;
}
public Builder addNote(String note){
course.setNote(note);
return this;
}
public Builder addHomework(String homework){
course.setHomework(homework);
return this;
}
public CourseInnerBuilder build(){
return course;
}
}
public static void main(String[] args) {
CourseInnerBuilder courseInnerBuilder = new CourseInnerBuilder.Builder()
.addName("设计模式")
.addPPT("PPT课件")
.addVideo("回放视频")
.addNote("课堂笔记")
.addHomework("课后作业").build();
System.out.println(courseInnerBuilder);
}
}
3 代理模式
当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过代理对象来间接访使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象。在代码中,一般代理会被理解为代码增强,实际上就是在原代码逻辑前后增加一些代码逻辑,而使调用者无感知。代理模式分为静态代理和动态代理。
3.1 JDK代理(重新实现接口,代理接口中的方法)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface IPerson{
void findLove();
}
class ZhangSan implements IPerson{
public void findLove() {
System.out.println("符合要求");
}
public void say(){
System.out.println("hello");
}
}
public class JDKMeipo implements InvocationHandler {
//被代理的对象
private IPerson target;
public IPerson getInstance(IPerson target){
this.target = target;
Class<? extends IPerson> clazz = target.getClass();
/*第一个参数: 用哪个类加载器去加载代理对象
第二个参数:动态代理类需要代理的方法
第三个参数:动态代理方法在执行时,会调用h里面的invoke方法去执行*/
return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object result = method.invoke(this.target, args);
after();
return result;
}
private void before(){
System.out.println("开始物色");
}
private void after(){
System.out.println("开始交往");
}
public static void main(String[] args) {
JDKMeipo jdkMeipo = new JDKMeipo();
IPerson zhangsanProxy = jdkMeipo.getInstance(new ZhangSan());
zhangsanProxy.findLove();
//代理类只能调用接口中的方法
// zhangsanProxy.say();
}
}
3.2 CGLib(通过继承,代理所有方法)
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
class Zhangsan{
public void findLove(){
System.out.println("符合要求");
}
}
public class CGLibMeipo implements MethodInterceptor {
public Object getInstance(Class<?> clazz) throws Exception{
//相当于JDK中的Proxy类,完成代理的工具类,通过继承实现
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
before();
Object res = methodProxy.invokeSuper(proxy, args);
after();
return res;
}
private void before(){
System.out.println("开始物色");
}
private void after(){
System.out.println("开始交往");
}
public static void main(String[] args) {
try{
Zhangsan obj = (Zhangsan)new CGLibMeipo().getInstance(Zhangsan.class);
obj.findLove();
}catch (Exception e){
e.printStackTrace();
}
}
}