1 动态代理
代理是什么?
代理其实就是代为处理的意思,个人理解就是产生一个处理类对需要代理的对象进行处理,并且返回该代理对象
静态代理
首先实现一个Moveable接口,表示代理与被代理的对象都属于同一个类别
public interface Moveable {
void move();
void stop();
}
接下来实现一个被代理对象坦克类,有着坦克开始与结束的方法
public class Tank implements Moveable{
@Override
public void move() {
System.out.println("Tank moving 。。");
try {
Thread.sleep(new Random().nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void stop() {
System.out.println("Tank stop");
}
}
接下来如果想要知道Tank的move方法允许了多久的话,最直接的就是使用继承方法,但是如果使用继承的话,想要再知道运行的日志的话就需要再继承扩展一个类,因此使用聚合来解耦合。
实现时间代理
public class TankTimeProxy implements Moveable{
Moveable t;
public TankTimeProxy(Moveable t) {
super();
this.t = t;
}
@Override
public void move() {
Long start = System.currentTimeMillis();
t.move();
long end = System.currentTimeMillis();
System.out.println(end-start);
}
@Override
public void stop() {
Long start = System.currentTimeMillis();
t.stop();
long end = System.currentTimeMillis();
System.out.println(end-start);
}
}
实现日志代理
public class TankLogProxy implements Moveable{
Moveable t;
public TankLogProxy(Moveable t) {
super();
this.t = t;
}
@Override
public void move() {
System.out.println("Tank start");
t.move(); //这里调用的其实是Tank的方法
long end = System.currentTimeMillis();
System.out.println("Tank end");
}
@Override
public void stop() {
}
}
调用地方的代码如下
public static void main(String[] args) throws NoSuchMethodException, IOException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
Tank t =new Tank();
TankTimeProxy ttp =new TankTimeProxy(t);
TankLogProxy tlp = new TankLogProxy(ttp); //在时间代理上再加上日志代理
// Moveable m = tlp;
Moveable m = tlp;
m.move();
}
打印数据的数据如下
Tank start
Tank moving 。。
861
Tank end
动态代理
(这里借用网上的例子,代码已经测过无误)
在完成了静态代理之后,我们需要考虑另外的问题,如果在我们需要计算的是除了move之外的其他方法的运行时间,那么岂不是又要生成一个代理类了?多个方法的话就是多个代理类,会导致类无限制扩展。因此就用到了动态代理
使用动态代理需要用到反射,反射是用于获取已创建实例的方法或者属性,并对其进行调用或者赋值。在这里我们可以动态一个代理对象,并且动态编译。然后,再通过反射创建对象并加载到内存中,就实现了对任意对象进行代理
第一步:定义自己的一个代理的逻辑处理接口,用来实现处理自定义逻辑
public interface InvocationHandler {
void invoke(Object o, Method m) throws InvocationTargetException, IllegalAccessException;
}
第二步:定义一个运行时间处理器,用来处理代理对象,
public class TimeHandler implements InvocationHandler {
//被代理的对象
private Object target;
public TimeHandler(Object target) {
this.target = target;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
// o 是代理对象
@Override
public void invoke(Object o, Method m) throws InvocationTargetException, IllegalAccessException {
long start = System.currentTimeMillis();
System.out.println("starttiem: "+ start);
m.invoke(target); //调用被代理对象原来的方法
long end = System.currentTimeMillis();
System.out.println("time: " + (end -start));
}
}
第三步:编写动态代理的代码:
public class Proxy {
/**
* 动态代理
* 产生新的代理类
* infce 产生对应接口的代理 该接口对应的处理方法
* @return
*/
public static Object newProxyInstance(Class infce, InvocationHandler h) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
String methodStr = "";
Method[] methods = infce.getMethods();
String rt = "\r\n";
for(Method m : methods) { //动态代码 编译后动态生成一个对象,该对象包含着InvocationHandler,
methodStr += "@Override" + rt +
"public void " + m.getName() + "() {" + rt +
" try {" + rt +
" Method md = " + infce.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +
" h.invoke(this, md);" + rt + //传入的是this
" }catch(Exception e) {e.printStackTrace();}" + rt +
"}";
}
String src =
"package com.bjsxt.proxy;" + rt +
"import java.lang.reflect.Method;" + rt +
"public class $Proxy1 implements " + infce.getName() + "{" + rt +
" public $Proxy1(InvocationHandler h) {" + rt +
" this.h = h;" + rt +
" }" + rt +
" com.bjsxt.proxy.InvocationHandler h;" + rt +
methodStr +
"}";
String fileName =
"d:/src/com/bjsxt/proxy/$Proxy1.java";
File f = new File(fileName);
FileWriter fw = new FileWriter(f);
fw.write(src);//将要编译的代码写到文件中去
fw.flush();
fw.close();
//编译TimeProxy源码
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable units = fileMgr.getJavaFileObjects(fileName);
JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
t.call();
fileMgr.close();
//加载到内存中并创建对象
URL[] urls = new URL[] {new URL("file:/" + "d:/src/")};
URLClassLoader ul = new URLClassLoader(urls);
Class c = ul.loadClass("com.bjsxt.proxy.$Proxy1");
System.out.println(c);
//传过来那个处理器就按照那个处理器去实现
Constructor ctr = c.getConstructor(InvocationHandler.class);
Object m = ctr.newInstance(h);
//m.move();
return m;
}
}
第四步:调用:
public static void main(String[] args) throws Exception {
Tank t = new Tank();
InvocationHandler h = new TimeHandler(t);
Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class, h);
m.move();
}
在这里Proxy.newProxyInstance(Moveable.class, h)生成的Proxy1代理类为:
class Prox1 implements Moveable {
private InvocationHandler handler;
public TimeProxy(InvocationHandler handler) {
this.handler = handler;
}
@Override
public void move() {
try {
Method method = com.youngfeng.proxy.Flyable.class.getMethod("move");
this.handler.invoke(this, method, null);
} catch(Exception e) {
e.printStackTrace();
}
}
}
方法调用链:Proxy1 . move() -> TimeHandler.invoke(Object o, Method m) -> Tank.move();
主要逻辑
- Proxy->newProxyInstance(infs, handler) 用于生成代理对象
- InvocationHandler:这个接口主要用于自定义代理逻辑处理
- 为了完成对被代理对象的方法拦截,我们需要在InvocationHandler对象中传入被代理对象实例。
因此对其他对象进行代理就不再需要修改newProxyInstance方法中的代码
2 策略模式
策略模式主要用于不同的类根据不同的方法去解决,比如一只猫的属性有体重跟身高,实现按身高进行排序与按体重进行排序,即可使用策略模式
- Comparable表明实现该接口的类必须实现compare方法,
- Comparator则是比较器的具体实现
第一步:定义一个实现了Comparable的Cat类
public class Cat implements Comparable{
int Height;
int weight;
Comparator comparator;
public int getHeight() {
return Height;
}
public void setHeight(int height) {
Height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public Comparator getComparator() {
return comparator;
}
public void setComparator(Comparator comparator) {
this.comparator = comparator;
}
@Override
public int compareTo(Object o) {
return comparator.compare(this, o);
}
}
在这个类里面实现了一个继承器,传入自己实现的Comparator可以实现对身高和体重进行比较。
第二步:实现一个接口类使它的实现类确定实现了compareTo方法
public interface Comparable {
int compareTo(Object o);
}
第三步:实现一个比较器的接口:
public interface Comparator {
int compare(Object o1, Object o2);
}
第四步:继承Comparator接口实现身高比较器
public class CatHeightComparator implements Comparator{
@Override
public int compare(Object o1, Object o2) {
Cat c1 = (Cat)o1;
Cat c2 = (Cat)o2;
if (c1.getHeight() > c2.getHeight()) return 1;
else if (c1.getHeight() > c2.getHeight()) return -1;
return 0;
}
}
策略模式其实就是需要变化的类其中聚合一个策略,根据需要传入不同的实现类实现不同的需要
3 状态模式
状态模式使用对象的形式来记录某种状态。使用状态模式可以省去多个if-else或者是switch的判断。可以直接使用对象方法的形式来处理逻辑。
例如在这里实现两个类Boy和MM类,其中MM中包含了抽象类State。代表了MM此时的心情
public class Boy {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class MM {
private MMState state = new MMHappyState();
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void smile(){
state.smile();
}
public void cry(){
state.cry();
}
public void say(){
state.say();
}
}
抽象类MyState
public abstract class MMState {
public abstract void smile();
public abstract void cry();
public abstract void say();
}
代表MM好心情的MMHappyState
public class MMHappyState extends MMState{
@Override
public void smile() {
}
@Override
public void cry() {
}
@Override
public void say() {
}
}
因此当MM状态改变时,比如从开心的哭变成悲伤的哭只需要改变State即可,不需要修改其他代码。
4 工厂模式
抽象工厂
当需要新的工厂时直接继承VehicleFactory就可以
第一步:Moveable接口
public interface Moveable {
void run();
}
所有的交通工具都实现了该接口
第二步:定义了汽车和飞机类
public class Plane implements Moveable{
@Override
public void run() {
System.out.println("plane");
}
}
public class Car implements Moveable{
private static Car c = new Car();
public void run(){
System.out.println("run");
}
//静态工厂方法 用来产生car产品
public static Car getInstance(){
return c;
}
}
第三步:实现一个工厂类,负责实现创建所有实例的内部逻辑。
public abstract class VehicleFactory {
abstract Moveable create();
}
第四步: 实现工厂接口
public class PlaneFactory extends VehicleFactory{
@Override
Moveable create() {
return new Plane();
}
}
public class CarFactory extends VehicleFactory{
@Override
Moveable create() {
return new Car();
}
}
在调用时需要那个类的工厂直接new它的工厂就行
public static void main(String[] args) {
VehicleFactory factory = new PlaneFactory();
Moveable m = factory.create();
m.run();
}
5 责任链模式
使多个对象都有处理请求的机会,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象串成一条链,并沿着这条链一直传递该请求,直到有对象处理它为止。
目标
用Filter模拟处理Request、Response
思路技巧
(1)Filter的doFilter方法改为doFilter(Request,Resopnse,FilterChain),有FilterChain引用,为利用FilterChain调用下一个Filter做准备
(2)FilterChain继承Filter,这样,FilterChain既是FilterChain又是Filter,那么FilterChain就可以调用Filter的方法doFilter(Request,Resopnse,FilterChain)
(3)FilterChain的doFilter(Request,Resopnse,FilterChain)中,有index标记了执行到第几个Filter,当所有Filter执行完后request处理后,就会return,以倒序继续执行response处理
代码如下:
Filter.java
public interface Filter {
void doFilter (Request request, Response response,FilterChain filterChain);
}
HTMLFilter.java :替换HTML代码
public class HTMLFilter implements Filter {
@Override
public void doFilter(Request request, Response response,
FilterChain filterChain) {
request.setRequestStr(request.getRequestStr().replace('<', '[').replace(">", "]")+"---HTMLFilter()");
filterChain.doFilter(request, response, filterChain);
response.setResponseStr(response.getResponseStr()+"---HTMLFilter()");
}
}
3.SensitiveFilter.java 替换敏感词汇
public class SensitiveFilter implements Filter {
@Override
public void doFilter(Request request, Response response,
FilterChain filterChain) {
request.setRequestStr(request.getRequestStr().replace("敏感", "幸福")+"---SensitiveFilter()");
filterChain.doFilter(request, response, filterChain);
response.setResponseStr(response.getResponseStr()+"---SensitiveFilter()");
}
}
4.FilterChian.java 过滤器链
public class FilterChain implements Filter {
private List<Filter> filters = new ArrayList<Filter>();
int index = 0; //标记执行到第几个filter
//把函数的返回值设为FilterChain,返回this,就能方便链式编写代码
public FilterChain addFilter(Filter filter) {
filters.add(filter);
return this;
}
public void doFilter(Request request, Response response, FilterChain fc) {
if(index == filters.size()) return ;
Filter f = filters.get(index);
index++;
f.doFilter(request, response, fc);
}
}
5.Request.java 和 Response.java
public class Request {
private String requestStr;
public String getRequestStr() {
return requestStr;
}
public void setRequestStr(String requestStr) {
this.requestStr = requestStr;
}
}
public class Response {
private String responseStr;
public String getResponseStr() {
return responseStr;
}
public void setResponseStr(String responseStr) {
this.responseStr = responseStr;
}
}
6Test.java
public class Test {
@org.junit.Test
public void testFilter(){
String msg = "<html>敏感字眼</html>";
Request request = new Request();
request.setRequestStr(msg);
Response response = new Response();
response.setResponseStr("response------------");
FilterChain fc = new FilterChain();
fc.addFilter(new HTMLFilter()).addFilter(new SensitiveFilter());
fc.doFilter(request, response, fc);
System.out.println(request.getRequestStr());
System.out.println(response.getResponseStr());
}
}
6 命令模式
命令也是类,将命令作为一个类来保存,当要使用的时候可以直接拿来使用
1.Client.java
public class Client {
public void request(Server server){
server.addCommand(new TextCommand());
server.addCommand(new ImageCommand());
server.doSomething();
}
}
2.Server.java
public class Server {
private List<Command> commands = new ArrayList<Command>();
public void doSomething() {
for(Command c : commands){
c.execute();
}
}
public void addCommand(Command command) {
commands.add(command);
}
}
3.Command.java
public abstract class Command {
public abstract void execute();
public abstract void unDo();
}
4.TextCommand.java
public class TextCommand extends Command {
@Override
public void execute() {
System.out.println("TextCommand...........");
}
@Override
public void unDo() {
// 涉及到操作的历史记录
}
}
5.ImageCommand.java
public class ImageCommand extends Command {
@Override
public void execute() {
System.out.println("ImageCommand...........");
}
@Override
public void unDo() {
// 涉及到操作的历史记录
}
}
6.Test.java
public class Test {
@org.junit.Test
public void test(){
Client c = new Client();
c.request(new Server());
}
}
7 桥接模式
设想如果要绘制矩形、圆形、椭圆、正方形,我们至少需要4个形状类,但是如果绘制的图形需要具有不同的颜色,如红色、绿色、蓝色等,此时至少有如下两种设计方案:
• 第一种设计方案是为每一种形状都提供一套各种颜色的版本。
• 第二种设计方案是根据实际需要对形状和颜色进行组合。
模式定义
桥接模式(Bridge Pattern):将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(Interface)模式
应用情况:(1)两个维度扩展(2)排列组合
1.Gift.java 礼物
public class Gift {
GiftImpl impl;
}
2.GiftImpl.java 继承该类是具体物品
public class GiftImpl {
}
3.WarmGift.java
public class WarmGift extends Gift {
public WarmGift(GiftImpl giftImpl) {
//调用父类的giftImpl
this.giftImpl = giftImpl;
}
@Override
public String toString() {
return this.getClass().getName()+"-----"+giftImpl.getClass().getName();
}
}
4.WildGift.java
public class WildGift extends Gift {
public WildGift(GiftImpl giftImpl) {
//调用父类的giftImpl
this.giftImpl = giftImpl;
}
@Override
public String toString() {
return this.getClass().getName()+"-----"+giftImpl.getClass().getName();
}
}
5.Flower.java
public class Folwer extends GiftImpl{
}
6.Ring.java
public class Ring extends GiftImpl{
}
7.MM.java
public class MM {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
8.Boy.java
pursue(MM mm)是送给女孩子礼物的方法 想要送不同的礼物修改gift = new WildGift(new Flower())即可
public class Boy {
private String name;
public void pursue(MM mm){
Gift gift = new WildGift(new Flower());
give(gift, mm);
System.out.println(gift);
}
public void give(Gift gift, MM mm) {
}
}
9.Test.java
public class Test {
@org.junit.Test
public void test() {
Boy b = new Boy();
b.pursue(new MM());
}
}