参考:
小猴子博客.http://www.monkey1024.com/%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f/1482
小猴子博客.http://www.monkey1024.com/%e8%ae%be%e8%ae%a1%e6%a8%a1%e5%bc%8f/1487
单例模式.https://www.runoob.com/design-pattern/singleton-pattern.html
浏览器设置代理.https://blog.csdn.net/weixin_42419856/article/details/81088665
文章目录
- 一、代理模式:
-
-
- 1.话说代理:
- 2.静态代理和动态代理:
-
-
- (1)静态代理:我找中间人,中间人找XiaoMan:
- (2)动态代理:
-
-
- 二、单例模式:
-
-
- 懒汉式和饿汉式:
-
- 三、工厂模式:
-
-
- 1.简单工厂模式(静态工厂):
- 2.工厂方法模式:
- 3.抽象工厂:
-
- 四、工厂模式的小应用:
-
-
- 1.复习工厂模式(简单工厂模式):
- 2.properties文件的应用:
- P.S:资源文件+反射+IO流:
- 3.资源文件+反射的简单工厂模式:
-
- 五、Spring中用到了工厂模式和单例模式:
-
-
- 1.配置Spring:
- 2.Spring中用到了工厂模式:
- 3.Spring中用到了单例模式:
-
- 六、其他设计模式:
- 七、适配器模式:
- 八、模板模式:
一、代理模式:
1.话说代理:
代理是什么意思?
我要打官司,但我对法律不太了解,于是请了个律师,让他代理我处理;
鄙人大学做了一个产品,被阿里相中了,阿里公司派来一个主管代理马云和我洽谈;
我们可以在浏览器设置一个代理服务器,用它来上网;
相信大家已经有所体会了,代理就是可以联系双方的中间人。
2.静态代理和动态代理:
详细介绍请点击这里
(1)静态代理:我找中间人,中间人找XiaoMan:
①Beauty接口:
②XiaoMan,You要调用的目标对象:
③静态代理中间人NaNa:
④You:
⑤测试类:
You调用makeFriend(),就是调用beauty.eat(),这里的beauty是naNa,
naNa的eat方法是beauty.eat(),这里的brauty是XiaoMan,
所以最终执行的是XiaoMan的eat()方法,You调用了XiaoMan的方法。
(2)动态代理:
动态代理就是你告诉Java一些参数,它来帮你自动生成中间的代理类。
JDK提供动态代理,底层使用反射原理,
但只能创建接口的代理,即例子中必须实现Beauty接口:
第一个参数是 目标类的类加载器;
第二个参数是 目标类的接口;
第三个参数是 InvocationHandler,代理中 实现的功能 写在该对象中;
通过这三个参数,得到代理类的对象。
第三个参数InvocationHandler的 invoke方法:调用代理类中的任何方法,此方法都会执行;
它的三个参数:
Object proxy: jdk创建出来的的动态代理对象自身的引用,Object类型的引用;
Method method:你要执行调用目标对象的哪个方法,比如XiaoMan的eat();
Object[] args:当前被调用方法用到的参数,比如eat()方法的参数,这里没参数,数组为空;
①测试类:
public class Test {
public static void main(String[] args) {
Beauty xiaoMan = new XiaoMan();
//不需要自己创建代理了
//NaNa naNa = new NaNa(xiaoMan);
//由jdk动态的为你创建一个代理
Beauty bproxy =
//java.lang.reflect.Proxy包导入,创建代理,传三个参数
(Beauty)Proxy.newProxyInstance(
xiaoMan.getClass().getClassLoader(),//目标类的类加载器
xiaoMan.getClass().getInterfaces(),//目标类的接口(jdk动态代理,只能创建目标类实现接口的代理对象)
new InvocationHandler() {//匿名内部类,重写invoke方法
@Override //invoke方法也要传三个参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("吃饭之前的准备");
Object invoke = method.invoke(xiaoMan);//操作的对象是xiaoMan,
//在这里真正调用Xiaoman的eat()方法
System.out.println("吃饭之后的结果");
return invoke;//返回Object对象
}
});
You you = new You(bproxy);
you.makeFriend();
}
}
②调用有参数的方法:
修改之前的测试类如下,送礼物的时候,为了感谢代理人,所以每次会把礼物分一半给代理人:
Beauty xiaoMan = new XiaoMan();
//不需要自己创建代理了
//NaNa naNa = new NaNa(xiaoMan);
//由jdk动态的为你创建一个代理
Beauty proxy = (Beauty)Proxy.newProxyInstance(xiaoMan.getClass().getClassLoader(), xiaoMan.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("准备");
Object invoke = null;
//makeFriend()和show()方法都会走到这里,需要加一个判断,根据方法名来判断
if ("gift".equals(method.getName())){
invoke = method.invoke(xiaoMan,new Object[]{(Integer)args[0]/2});//参数变换,
//args[0]为10,是方法method传的参数
//中间商抽取一半礼物,(Integer)args[0]/2}
}else{//"eat".equals(method.getName())
invoke = method.invoke(xiaoMan);
}
System.out.println("结果");
return invoke;//返回invoke
}
});
You you = new You(proxy);
you.makeFriend();
you.show();
ps:我的理解:
静态代理:我调用Nana,Nana调用XiaoMan;
动态代理:我调用系统的接口,这个接口通过反射调用XiaoMan。
二、单例模式:
单例类只能有一个实例,你要用,就通过函数去取这一个实例。
①创建一个单例类。
public class SingleObject {
//创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
private SingleObject(){}
//获取唯一可用的对象
public static SingleObject getInstance(){
return instance;
}
public void showMessage(){
System.out.println("Hello World!");
}
}
②从单例类获取唯一的对象。
public class SingleTest {
public static void main(String[] args) {
//不合法的构造函数
//编译时错误:构造函数 SingleObject() 是不可见的
//SingleObject object = new SingleObject();
//获取唯一可用的对象
SingleObject object = SingleObject.getInstance();
//显示消息
object.showMessage();
}
}
懒汉式和饿汉式:
true true
三、工厂模式:
我们生活中要用斧子,不可能现做,而是去工厂里面买;
编程中我们要用对象,不用自己new,而是从工厂中去取。
这样,可以降低程序之间的耦合度,
所以,以后创建对象的工作就交给
1.简单工厂模式(静态工厂):
详细介绍请点击这里
工厂根据字符串,返回相应的对象
2.工厂方法模式:
详细介绍请点击这里
工厂接口下实现不同的工厂
3.抽象工厂:
详细介绍请点击这里
相比于工厂方法模式,在其中多写几个方法
四、工厂模式的小应用:
1.复习工厂模式(简单工厂模式):
①先创建一个水果工厂:
②创建水果接口、苹果类、葡萄类:
③创建测试类并运行:
小结一下:
这里我们用到了工厂模式,使得类的使用者和创建者分离,
但是,代码可能有需求要修改,比如加入新水果,那么,工厂类的代码就要跟着修改。
所以我们可以使用工厂方法模式,这里,我们用另一个方法,也可以实现不修改源代码更新项目,
那就是用properties资源文件+反射的简单工厂模式。
2.properties文件的应用:
①properties文件是以键值对的形式存储的,
在firstjava项目的propertiesDemo包下,我创建了aa.properties文件如下:
②创建PropertiesDemo类,这个类通过绝对路径加载了这个properties文件,并输出了aa的值
③如果使用绝对路径,假如我拷贝这个项目到另一台电脑上,路径就不对了,
所以,我们可以使用项目路径(相对路径),
创建PropertiesDemo2类,有两种方法来实现获取当前项目的src路径:
P.S:资源文件+反射+IO流:
①接口与实现类:
②资源文件:
③测试类:
3.资源文件+反射的简单工厂模式:
properties文件:属性文件
里面存储的数据是key-value
中间以=或者:或者空格将key和value隔开
如果一行有多个=、:、空格存在
则以最前面出现的作为分隔符
①创建一个新的包,叫做propertiesTry,里面的三个文件和上面一样:
②创建一个properties资源文件,里面是苹果java文件的“包名+类名”,因为一会要用到反射:
③创建工厂类,这里用静态代码块导入properties文件(静态块只执行一次),拿到苹果类的路径,
用反射的方法的方法得到苹果类的实例:
④Test1类用来测试,成功返回苹果对象:
⑤现在,我要加一个Banana类:
⑥这时,我仅仅需要修改properties文件,我就可以通过工厂返回Banana的对象:
五、Spring中用到了工厂模式和单例模式:
Spring相当于项目的大管家,其中的一项功能就是管理对象的创建。
官方名词叫做IOC(Inversion of Control) 控制反转 ,
即把对象创建的控制权有你来new反转为spring来做,
再将创建好的对象注入给使用者,就是 依赖注入 了。
1.配置Spring:
详细配置过程点击这里
大概步骤是:
①添加依赖jar包
②添加spring的配置文件
③用对象时,获取配置文件,再根据配置文件的id用反射的方式创建对象
2.Spring中用到了工厂模式:
详细用法点击这里
通过控制反转获取的对象,有三种方式:
①默认方式
②实例工厂
③静态工厂
3.Spring中用到了单例模式:
详细用法点击这里
用控制反转创建的对象,默认都是单例模式的,如果有需要,
也可以在spring配置文件的属性中,修改tpye属性,改为别的模式。
singleton: 单例模式,默认。
prototype: 原型模式。即每次使用 getBean 方法获取的的实例都是一个新的实例。
request:对于每次 HTTP 请求,都将会产生一个不同的 Bean 实例。
session:对于每个不同的 HTTP session,都将产生一个不同的 Bean 实例。
application:在一个web应用中会产生一个bean实例,就相当于在一个ServletContext中只有该bean的实例。
websocket:在一个websocket中会产生一个bean实例。
六、其他设计模式:
1.工厂模式:创建实例不用自己去new,而是从工厂中获取;
2.代理模式:找了一个代理类来当中介,NaNa,来创建对象‘
3.桥接模式:JFBC提供统一入口;
4.装饰器模式:不想继承,但又想修改某一方法,和代理模式区别在需要传入实例;
5.组合模式:树和节点;
6.外观模式:电脑与CPU、Disk、Memory的关系,统一外观方法名 ;
7.享元模式:池,Final,HashMap容器键值对;
8.原型模式:浅拷贝共用内存,深拷贝不共用,Java对象默认浅拷贝;
9.单例模式:控制用的对象都是一个,构造器私有;
10.适配器模式(类、对象、接口):覆盖操作;
11.策略模式:接口可以多个实现,策略选择;
12.模板模式:final模板永远调用;
13观察者模式:创建观察者、主题,主题add观察者,主题更新通知观察者;
14.迭代器模式:集合,迭代;
15.责任链模式:链表;
16.命令模式:Linux;
17.备忘录模式:备份恢复,命令根据不同执行者做不同操作 ;
18.状态模式:QQ上线下线;
七、适配器模式:
原本实现Servlet接口的Servlet类要实现很多方法,比如init、service、destory方法等
GenericServlet类用了适配器模式:
现在servlet只需继承GenericServlet类,实现service方法
GenericServlet类已经实现了Servlet, ServletConfig接口
适配器是一个万能充电接口,
充电接口(GenericServlet类)一端连接安卓手机的充电器(servlet),
另一端连接苹果手机(service接口),这样就实现了使用安卓手机的充电器给苹果手机充电了。
八、模板模式:
定义抽象类,里面有抽象方法,让子类必须自己实现这些抽象方法
HttpServlet使用了模板模式,它里面会运行doGet方法,
自己也写了doGet方法,但里面没写啥,希望继承类去自己实现。