设计模式 复习整理(仗剑走天涯) 常用的简单设计模式 工厂设计模式 工厂模式分为简单工厂模式,工厂方法模式和抽象工厂模式,它们都属于设计模式中的创建型模式。其主要功能都是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代码耦合度,并且增强了系统的扩展性。
还有一个很重要的原因,就是对象的创建过程比较复杂,使用工厂模式进行封装,同时可以屏蔽掉对象的复杂的创建过程
简单工厂设计模式 简单工厂模式最大的优点在于实现对象的创建和对象的使用分离,将对象的创建交给专门的工厂类负责,但是其最大的缺点在于工厂类不够灵活,增加新的具体产品需要修改工厂类的判断逻辑代码,而且产品较多时,工厂方法代码将会非常复杂
工厂角色负责实现创建所有实例的内部逻辑
1 2 3 4 5 6 7 8 9 10 11 12 public class FriendFactory { public Friend friendName (String name) { if (name.contentEquals("胖子" )){ return new FattyFriend(); }else if (name.contentEquals("SB铭" )){ return new SBFriend(); }else { throw new RuntimeException("没有此朋友" ); } } }
抽象产品角色是所创建的所有对象的父类,负责描述所有实例所共有的公共接口
1 2 3 4 5 public interface Friend { public void play () ; }
具体产品角色是创建目标,所有创建的对象都充当这个角色的某个具体类的实例
1 2 3 4 5 6 7 public class FattyFriend implements Friend { @Override public void play () { System.out.println("胖子" ); } }
1 2 3 4 5 6 public class SBFriend implements Friend { @Override public void play () { System.out.println("SB" ); } }
1 2 3 4 5 6 7 8 9 public class Client { public static void main (String[] args) { FriendFactory friendFactory = new FriendFactory(); Friend friend = friendFactory.friendName("SB铭" ); friend.play(); } }
工厂方法模式
1 2 3 4 5 public interface Factory { public Friend Friend () ; }
1 2 3 4 5 6 7 8 public class FattyFriendFactory implements Factory { @Override public FattyFriend Friend () { return new FattyFriend(); } }
1 2 3 4 5 6 7 public class SBFriendFactory implements Factory { @Override public Friend Friend () { return new SBFriend(); } }
1 2 3 4 5 public interface Friend { public void play () ; }
1 2 3 4 5 6 7 public class FattyFriend implements Friend { @Override public void play () { System.out.println("胖子" ); } }
1 2 3 4 5 6 public class SBFriend implements Friend { @Override public void play () { System.out.println("SB" ); } }
1 2 3 4 5 6 7 8 9 public class Client { public static void main (String[] args) { Factory factory = new SBFriendFactory(); Friend friend = factory.Friend(); friend.play(); } }
好处
此模式中,通过定义一个抽象的核心工厂类,并定义创建产品对象的接口,创建具体产品实例的工作延迟到其工厂子类去完成。这样做的好处是核心类只关注工厂类的接口定义,而具体的产品实例交给具体的工厂子类去创建。当系统需要新增一个产品是,无需修改现有系统代码,只需要添加一个具体产品类和其对应的工厂子类,使系统的扩展性变得很好,符合面向对象编程的开闭原则
缺点
工厂方法模式虽然扩展性好,但是增加了编码难度,大量增加了类的数量,所以怎么选择还是看实际的需求
抽象工厂模式 在有多个业务品种、业务、分类时,通过抽象工厂模式产生需要的对象是一种非常好的解决方式
1 2 3 4 5 6 7 public abstract class AbstractFactory { public abstract AbstractManFriend manFriend () ; public abstract AbstractGiriFriend giriFriend () ; }
1 2 public abstract class AbstractGiriFriend {}
1 2 public abstract class AbstractManFriend {}
1 2 3 4 5 6 7 8 9 10 11 public class AFriendFactory extends AbstractFactory { @Override public AbstractManFriend manFriend () { return new AManFriend(); } @Override public AbstractGiriFriend giriFriend () { return new AGiriFriend(); } }
1 2 3 public class AGiriFriend extends AbstractGiriFriend {}
1 2 public class AManFriend extends AbstractManFriend {}
1 2 3 4 5 6 7 8 9 10 11 public class BFriendFactory extends AbstractFactory { @Override public AbstractManFriend manFriend () { return new BManFriend(); } @Override public AbstractGiriFriend giriFriend () { return new BGiriFriend(); } }
1 2 public class BGiriFriend extends AbstractGiriFriend {}
1 2 public class BManFriend extends AbstractManFriend {}
1 2 3 4 5 6 7 8 9 10 public class Client { public static void main (String[] args) { AbstractFactory abstractFactory = new AFriendFactory(); AbstractManFriend abstractManFriend = abstractFactory.manFriend(); System.out.println(abstractManFriend); } }
创建者模式 分离对象子组件的单独构造(由Buider来负责)和装配(由Director负责)。从而可以构造出复杂的对象。这个模式适用于:某个对象的构建过程复杂的情况下使用。
由于实现构造和装配的解耦。不同的构造器,相同的装配,也可以做出不同的对象;相同的构造器,不同的装配顺序也可以做出不同的对象。也就是实现了构建算法、装配算法的解耦,实现了更好的复用。
最典型的就是我们的StringBuilder和StringBuffer。
Builder:抽象建造者
ConcreteBuilder:具体建造者
Director:指挥者
Product:产品角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 public class Lifecycle { private String birth; private String school; private String work; private String marriage; private String die; public String getBirth () { return birth; } public void setBirth (String birth) { this .birth = birth; } public String getSchool () { return school; } public void setSchool (String school) { this .school = school; } public String getWork () { return work; } public void setWork (String work) { this .work = work; } public String getMarriage () { return marriage; } public void setMarriage (String marriage) { this .marriage = marriage; } public String getDie () { return die; } public void setDie (String die) { this .die = die; } public static class Builder { private final Lifecycle lifecycle = new Lifecycle(); public Builder builderBirth (String birth) { lifecycle.setBirth(birth + "我来到了这世间" ); return this ; } public Builder builderSchool (String school) { lifecycle.setSchool(school + "开始上学" ); return this ; } public Builder builderWork (String work) { lifecycle.setWork(work + "毕业开始工作" ); return this ; } public Builder builderMarriage (String marriage) { lifecycle.setMarriage(marriage + "***" ); return this ; } public Builder builderDie (String die) { lifecycle.setDie(die + "死去" ); return this ; } public Lifecycle builder () { return lifecycle; } } @Override public String toString () { return "Lifecycle{" + "birth='" + birth + '\'' + ", school='" + school + '\'' + ", work='" + work + '\'' + ", marriage='" + marriage + '\'' + ", die='" + die + '\'' + '}' ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public class Client { public static void main (String[] args) { Lifecycle lifecycle = new Lifecycle.Builder().builderBirth("2001-04-06" ) .builderSchool("2006-09-01" ) .builderWork("2023-07-01" ) .builderMarriage("****" ) .builderDie("某年某月某日" ) .builder(); System.out.println(lifecycle); } }
创建者模式是一个对对象的构建过程“精细化”的构建过程,每个部分的构建可能是变化的,但是对象的组织过程是固定的,通过这种统一的创建方式,无疑增加了我们设计上的灵活性,当我们在构建复杂对象的时候,我们如果发现每个部分可能都是变化的,并且是多个不同的构建步骤的时候,我们可以考虑使用创建者模式
代理设计模式 代理的核心功能是方法增强
静态代理模式 抽象角色 : 一般使用接口或者抽象类来实现
真实角色 : 被代理的角色
代理角色 : 代理真实角色 ; 代理真实角色后 , 一般会做一些附属的操作
客户 : 使用代理角色来进行一些操作
静态代理的两种方式
不同对象实现相同接口
1 2 3 4 5 public interface Bossinterface { public void project () ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Boss implements Bossinterface { private String name; public Boss (String name) { this .name = name; } @Override public void project () { System.out.println(name + "要做个项目" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class Proxy implements Bossinterface { private Boss boss; public Proxy (Boss boss) { this .boss = boss; } @Override public void project () { System.out.println("项目经理给我想法子" ); System.out.println("策划给我设计" ); boss.project(); System.out.println("程序员给我写" ); System.out.println("运维给我善后" ); } }
1 2 3 4 5 6 7 8 public class Client { public static void main (String[] args) { Bossinterface bossinterface = new Proxy(new Boss("Boss" )); bossinterface.project(); } }
1 2 3 4 5 public class Boss { public void project () { System.out.println("老板一个大饼我要做个新项目" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 public class Proxy extends Boss { @Override public void project () { System.out.println("项目经理给我想法子" ); System.out.println("策划给我设计" ); super .project(); System.out.println("程序员给我写" ); System.out.println("运维给我善后" ); } }
1 2 3 4 5 6 7 public class Client { public static void main (String[] args) { Proxy proxy = new Proxy(); proxy.project(); } }
优点
公共的统一问题交给代理处理
公共业务进行扩展或变更时,可以更加方便
缺点
每个类都写个代理
动态代理模式 动态代理的代理类是动态生成的 ,静态代理的代理类是我们写的
动态代理分为两类 : 一类是基于接口动态代理 , 一类是基于类的动态代理
基于接口的动态代理—-JDK动态代理
基于类的动态代理–cglib
JDK源生动态代理 jdk动态代理的两个核心类
1 2 3 4 5 6 public Object invoke ( Object proxy, final Method method, Object[] args ) throws Throwable {}
proxy
调用该方法的代理实例
method
所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
args
包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
1 2 3 4 @CallerSensitive public static Object newProxyInstance (ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {}
loader
加载路径
interfaces
接口类 是个数组 可以是多个
InvocationHandler
invocationHandler接口
1 2 3 4 5 public interface Bossinterface { public void project () ; }
1 2 3 4 5 public class Boss { public void project () { System.out.println("老板一个大饼我要做个新项目" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class DynamicProxy implements Bossinterface { private Boss boss; public DynamicProxy () { } public DynamicProxy (Boss boss) { this .boss = boss; } @Override public void project () { System.out.println("项目经理给我想法子" ); System.out.println("策划给我设计" ); boss.project(); System.out.println("程序员给我写" ); System.out.println("运维给我善后" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class JdkDynamicProxy { public static void main (String[] args) { System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles" , "true" ); Bossinterface proxy = (Bossinterface)Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), new Class[]{Bossinterface.class}, new myInvocationHandler(new DynamicProxy(new Boss()))); proxy.project(); } public static class myInvocationHandler implements InvocationHandler { private Bossinterface bossinterface; public myInvocationHandler (Bossinterface bossinterface) { this .bossinterface = bossinterface; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { method.invoke(bossinterface); return null ; } } }
cglib动态代理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <dependencies > <dependency > <groupId > cglib</groupId > <artifactId > cglib</artifactId > <version > 3.3.0</version > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.apache.maven.plugins</groupId > <artifactId > maven-compiler-plugin</artifactId > <version > 3.8.1</version > <configuration > <source > 1.8</source > <target > 1.8</target > <encoding > utf-8</encoding > </configuration > </plugin > </plugins > </build >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void main (String[] args) { Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(MaleSinger.class); enhancer.setCallback(new MethodInterceptor() { public Object intercept (Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("---------" ); Object invoke = methodProxy.invokeSuper(o,objects); System.out.println("++++++++++" ); return invoke; } }); MaleSinger maleSinger = (MaleSinger)enhancer.create(); maleSinger.sing(); }
Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承)
CGLIB能够代理普通类
Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效
ASM动态代理的本质 ASM是一个java字节码操纵和分析框架,它可以直接以二进制的形式修改class或动态生成class
1 2 3 4 5 6 7 8 9 10 <dependency > <groupId > org.ow2.asm</groupId > <artifactId > asm-util</artifactId > <version > 8.0.1</version > </dependency > <dependency > <groupId > org.ow2.asm</groupId > <artifactId > asm</artifactId > <version > 8.0.1</version > </dependency >
你知道的越多 你不知道的越多 嘿 我是小博 带你一起看我目之所及的世界……