因为很多时候完成技术选型后,走逻辑的时候总发现软件设计中普遍存在(反复出现)的各种因为设计而产生的冗余性问题,就所提出的解决方案而言,总是没有一个很好的汇总,因此今天搬运一些常见的设计模式(虽然有好几种都没用过hhhhh)。
设计模式 | 典型应用 | 框架中的应用 |
---|---|---|
工厂方法 | 适合在单个产品上做纬度扩展 | |
抽象工厂 | 适合在产品族的纬度上扩展 | bean工厂 |
Mediator 调节模式 | 消息中间件(内部之间调和)(居委会大妈) | mq |
Facade 门面模式 | 将复杂的服务整合,当用户访问后,可以通过简单的方式访问到复杂的服务(包工头) | |
责任链模式 | 需要用状态来确定责任是否完成,通常需要用boolean来确定 | Filter Interceptor,Filter中FilterChain负责调用的顺序,里面是一个递归的方法 |
Observer观察者 | 事件处理模型 | |
Decorator装饰器 | 顾名思义,就是在原来的基础上在加一层装饰,装饰的类和被装饰的类都可以横向扩展(在开发的时候,就是类在继承,而方法在嵌套) | 在IO流中,比如Reader 包含InputStream |
观察者模式Observer | 观察者很少和事件源打交道,主要是和事件打交道,和Listener,hook function,callback function 都是观察者 | 很多系统中,Observer模式往往和负责责任链共同负责对于事件的处理,其中某一个observer负责是否将事件进一步传递 |
组合Composite | 树状结构专用模式 | 可用于导航栏 |
享元Flyweight | 重复利用对象,共享元数据,有池化的概念 | String 就是这个模式,使用的时候 可以和组合模式一起使用 |
代理模式 | 静态代理,动态代理,springAop,代理也实现被代理类的接口,并在代理类中将接口类作为成员变量 | 有点类似 Decorator jdk实现的动态代理需要 实体类实现了接口 cglib可以对任何类进行动态代理 |
Iteratror迭代器 | 容器,容器遍历 | 其实就是多态的一个应用 |
Visitor访问者 | 在结构不变的情况下动态改变对于内部元素的动作 | |
ASM | Iteratror+Visitor+chainfresposibility | |
builder | 构建复杂的对象 | 链式编程(在类的众多参数中,你只需要其中的一些时候,使用该模式,看代码) |
Adapter(Wrapper) | 接口转换器 | 相当于插线板的转接头一样,加一层 |
Bridge | 双纬度扩展 | 分离抽象和具体 |
Command | 封装命令(doit和undo方法) | 别名:Action/Transaction |
Prototype原型模式/克隆模式 | Object.clone() Object 自带clone模式 | 有浅克隆和深克隆区分 |
Memento备忘录 | 记录状态便于回滚 | 记录快照(瞬时状态),存盘,使用File做序列化时,使用transient 表示透明的,不需要存盘,需要存盘的都需要实现序列化接口,或者父类实现序列化接口,在网络传输中序列化通常使用google的ProtoBuf |
TemplateMethod模版方法(钩子函数) | ||
State状态模式 | 根据状态决定行为 | |
Intepreter解析器 | 动态脚本解析 |
记住典型的用法和类图
静态代理
/** * 问题:我想记录坦克的移动时间 * 最简单的办法:修改代码,记录时间 * 问题2:如果无法改变方法源码呢? * 用继承? * v05:使用代理 * v06:代理有各种类型 * 问题:如何实现代理的各种组合?继承?Decorator? * v07:代理的对象改成Movable类型-越来越像decorator了 * */ public class Tank implements Movable { /** * 模拟坦克移动了一段儿时间 */ @Override public void move() { System.out.println("Tank moving claclacla..."); try { Thread.sleep(new Random().nextInt(10000)); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { Tank t = new Tank(); TankTimeProxy ttp = new TankTimeProxy(t); TankLogProxy tlp = new TankLogProxy(ttp); tlp.move(); // new TankLogProxy( // new TankTimeProxy( // new Tank() // ) // ).move(); } } class TankTimeProxy implements Movable { Movable m; public TankTimeProxy(Movable m) { this.m = m; } @Override public void move() { long start = System.currentTimeMillis(); m.move(); long end = System.currentTimeMillis(); System.out.println(end - start); } } class TankLogProxy implements Movable { Movable m; public TankLogProxy(Movable m) { this.m = m; } @Override public void move() { System.out.println("start moving..."); m.move(); long end = System.currentTimeMillis(); System.out.println("stopped!"); } } interface Movable { void move(); }
动态代理
/** * 问题:我想记录坦克的移动时间 * 最简单的办法:修改代码,记录时间 * 问题2:如果无法改变方法源码呢? * 用继承? * v05:使用代理 * v06:代理有各种类型 * 问题:如何实现代理的各种组合?继承?Decorator? * v07:代理的对象改成Movable类型-越来越像decorator了 * v08:如果有stop方法需要代理... * 如果想让LogProxy可以重用,不仅可以代理Tank,还可以代理任何其他可以代理的类型 * (毕竟日志记录,时间计算是很多方法都需要的东西),这时该怎么做呢? * 分离代理行为与被代理对象 * 使用jdk的动态代理 * * v09: 横切代码与业务逻辑代码分离 AOP * v10: 通过反射观察生成的代理对象 * jdk反射生成代理必须面向接口,这是由Proxy的内部实现决定的 */ public class Tank implements Movable { /** * 模拟坦克移动了一段儿时间 */ @Override public void move() { System.out.println("Tank moving claclacla..."); try { Thread.sleep(new Random().nextInt(10000)); } catch (InterruptedException e) { e.printStackTrace(); } } public static void main(String[] args) { Tank tank = new Tank(); System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles","true"); Movable m = (Movable)Proxy.newProxyInstance(Tank.class.getClassLoader(), new Class[]{Movable.class}, //tank.class.getInterfaces() new TimeProxy(tank) ); m.move(); } } class TimeProxy implements InvocationHandler { Movable m; public TimeProxy(Movable m) { this.m = m; } public void before() { System.out.println("method start.."); } public void after() { System.out.println("method stop.."); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Arrays.stream(proxy.getClass().getMethods()).map(Method::getName).forEach(System.out::println); before(); Object o = method.invoke(m, args); after(); return o; } } interface Movable { void move(); }
链式编程 builder模式
public class Person { int id; String name; int age; double weight; int score; Location loc; private Person() {} public static class PersonBuilder { Person p = new Person(); public PersonBuilder basicInfo(int id, String name, int age) { p.id = id; p.name = name; p.age = age; return this; } public PersonBuilder weight(double weight) { p.weight = weight; return this; } public PersonBuilder score(int score) { p.score = score; return this; } public PersonBuilder loc(String street, String roomNo) { p.loc = new Location(street, roomNo); return this; } public Person build() { return p; } } public static void main(String[] args) { Person p = new Person.PersonBuilder() .basicInfo(1, "zhangsan", 18) //.score(20) .weight(200) //.loc("bj", "23") .build(); } } class Location { String street; String roomNo; public Location(String street, String roomNo) { this.street = street; this.roomNo = roomNo; } }标签:System,String,汇总,代理,Movable,问题,new,设计模式,public From: https://blog.csdn.net/qq_56394739/article/details/143990611