java通关整理汇总-Java基础、计算机网络、数据库、设计模式、框架、算法模板、笔试
网上收集整理,仅做笔记参考学习
1.单例模式
确保一个类只有一个实例,并提供该实例的全局访问点。
优点:
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。
懒汉式-线程不安全
懒汉式,顾名思义就是实例在用到的时候才去创建
1、懒汉式,线程不安全
是否 Lazy 初始化:是
是否多线程安全:否
实现难度:易
描述:这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。
public class Singleton{
private static Singleton intance;
//构造器
private Singleton(){
}
public static Singleton getInstance(){
if(intance == null){
intance = new Singleton();
}
return intance;
}
}
懒汉式-线程安全
区别就是是否getInstance()
是否由synchronized
关键字
是否多线程安全:是
缺点:必须加锁 synchronized
才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)
public class Singleton{
private static Singleton intance;
//构造器
private Singleton(){
}
public static synchronized Singleton getInstance(){
if(intance == null){
intance = new Singleton();
}
return intance;
}
}
饿汉式
是否 Lazy 初始化:否
是否多线程安全:是
描述:这种方式比较常用,但容易产生垃圾对象。
优点:没有加锁,执行效率会提高。
缺点:类加载时就初始化,浪费内存。
instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。
public class Singleton{
private static Singleton instance = new Singleton();
//构造器
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
2.代理模式
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。
缺点:
1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
1.创建一个Image类
public interface Image {
void display();
}
2.1创建Image类的实现类ImpImage
public class ImpImage implements Image {
private String fileName;
public ImpImage(String fileName) {
this.fileName = fileName;
loadImage(fileName);
}
@Override
public void display() {
System.out.println("displaying " + fileName);
}
private void loadImage(String fileName){
System.out.println("loading " + fileName);
}
}
2.2创建Image类的代理实现类ImpProxyImage
public class ImpProxyImage implements Image {
private String fileName;
private ImpImage impImage;
public ImpProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if(impImage == null){
impImage = new ImpImage(fileName);
}
impImage.display();
}
}
3.当被请求时,使用ImpProxyImage来获取ImpImage
类的对象
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ImpProxyImage("image_10");
image.display();//第一次impImage为null,所以需要加载
image.display();//第二次不为空,所以直接调用方法
}
}
运行结果
第一次impImage为null,所以需要加载后,在调用方法
第二次不为空,所以直接调用方法
loading image_10
displaying image_10
displaying image_10
3. 观察者模式
观察者模式也叫发布-订阅模式,通俗的来讲,就和我们平时关注微信公众号一样,我们用户关注微信公众号,然后当微信公众号发布新信息时,就可以一个个的发布信息。使得关注的人都可以看到发布的消息。
举个最简单的例子:
观察者模式需要一个subject类,一个观察者的接口,几个观察者接口的实现类,方法测试类。观察者订阅被观察者的状态,当被观察者状态改变的时候会通知所有订阅的观察者的过程。
把下面的代码说完之后就可以引到redis的发布订阅上,然后redis说完,面试官可能就会问其他的消息队列问题,kafka等…
被观察者:
public class Subject {
private List<Observer> observers = new ArrayList<>(); //状态改变
public void setMsg(String msg) {
notifyAll(msg);
}
//订阅
public void addAttach(Observer observer) {
observers.add(observer);
}
//通知所有订阅的观察者
private void notifyAll(String msg) {
for (Observer observer : observers) {
observer.update(msg);
}
}
}
观察者接口:
public abstract class Observer {
public abstract void update(String msg);
}
第一个观察者:
public class F_Observer extends Observer {
public void update(String msg) {
System.out.println(F_Observer.class.getName() + " : " + msg);
}
}
第二个观察者:
public class S_Observer extends Observer {
public void update(String msg) {
System.out.println(S_Observer.class.getName() + " : " + msg);
}
}
第三个观察者:
public class T_Observer extends Observer {
public void update(String msg) {
System.out.println(T_Observer.class.getName() + " : " + msg);
}
}
使用方法:
public class Main {
public static void main(String[] args) {
F_Observer fObserver = new F_Observer();
S_Observer sObserver = new S_Observer();
T_Observer tObserver = new T_Observer();
Subject subject = new Subject();
subject.addAttach(fObserver);
subject.addAttach(sObserver);
subject.addAttach(tObserver);
subject.setMsg("msg change");
}
}
运行结果:
test.F_Observer : msg changetest.S_Observer : msg changetest.T_Observer : msg change