设计模式 | 典型应用 | 框架中的应用 |
---|---|---|
工厂方法 | 适合在单个产品上做纬度扩展 | |
抽象工厂 | 适合在产品族的纬度上扩展 | 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;
}
}
PREVIOUSJava中ArrayList和LinkedList的性能分析