设计模式1【单例模式、观察者模式、工厂模式】

本文深入讲解了单例模式的多种实现方式,包括饿汉式、懒汉式等,并探讨了如何防止序列化破坏单例。同时,介绍了观察者模式在实际场景中的应用,如一键启动多台机器的实例。此外,还详细解析了工厂模式的不同形态,如简单工厂、工厂方法和抽象工厂,以视频生产和播放器创建为例进行说明。

单例模式

一、饿汉式:

package single;
public class EagerSingleton {
	private final static EagerSingleton EAGER_SINGLETON = new EagerSingleton();
	private EagerSingleton() {}
	public static EagerSingleton getInstance() {
		return EAGER_SINGLETON;
	}
}

二、普通懒汉式:

public class LazySingleton {
	private static LazySingleton lazySingleton = null;
	private LazySingleton() {}
	
	public static LazySingleton getInstance() {
		if(lazySingleton == null) {
			lazySingleton = new LazySingleton();
		}
		return lazySingleton;
	}
}

三、线程安全懒汉式:

public class LazySingletonSafe {
	private static LazySingletonSafe lazySingleton = null;
	private LazySingletonSafe() {}
	
	public synchronized static LazySingletonSafe getInstance() {
		if(lazySingleton == null) {
			lazySingleton = new LazySingletonSafe();
		}
		return lazySingleton;
	}
}

四、双重校验懒汉式:

public class LazySingletonDoubleCheck {
	private volatile static LazySingletonDoubleCheck lazySingleton = null;
	private LazySingletonDoubleCheck() {}
	
	public static LazySingletonDoubleCheck getInstance() {
		if(lazySingleton == null) {
			synchronized(LazySingletonDoubleCheck.class){
				if(lazySingleton == null) {
					lazySingleton = new LazySingletonDoubleCheck();
				}
			}
		}
		return lazySingleton;
	}
}

五、静态内部类式:

public class StaticInnerClassSingleton {
	private StaticInnerClassSingleton() {}
	private static class StaticInnerClassSingletonLoader{
		public static final StaticInnerClassSingleton singleton = new StaticInnerClassSingleton();
	}
	public static StaticInnerClassSingleton getInstance() {
		return StaticInnerClassSingletonLoader.singleton;
	}
}

六、防止序列化破坏的单例

增加readResolve方法,这样调用反序列化时,会返回内存存在的单例对象实体

import java.io.Serializable;

public class LazySingleton implements Serializable{
	private static final long serialVersionUID = 1L;
	
	private static LazySingleton lazySingleton = null;
	private LazySingleton() {}
	
	public static LazySingleton getInstance() {
		if(lazySingleton == null) {
			lazySingleton = new LazySingleton();
		}
		return lazySingleton;
	}
	
	private Object readResolve() {
		return lazySingleton;
	}
}

观察者模式

以按下按钮启动机器为例,用观察者模式实现该功能。

设置机器一 、机器二 

import java.util.Observable;
import java.util.Observer;

public class Machine1 implements Observer {
	
	Button button ;
	public Machine1(Button button) {
		 this.button = button;
		 button.addObserver(this);
	}
	
	@Override
	public void update(Observable o, Object arg) {
		System.out.println("Machine1接收指令:"+arg);
		System.out.println("Machine1已启动");
	}
}

 

import java.util.Observable;
import java.util.Observer;

public class Machine2  implements Observer {
	Button button ;
	public Machine2(Button button) {
		 this.button = button;
		 button.addObserver(this);
	}
	
	@Override
	public void update(Observable o, Object arg) {
		System.out.println("Machine2接收指令:"+arg);
		System.out.println("Machine2已启动");
	}
	
}

设置一键启动按钮 

public class Button extends Observable{
	public void notifyMachine(){
        setChanged();    //必须调用的方法,底层实现是设置变更标志位为True
        notifyObservers("发出启动指令"); //向所有注册的观察者发布最新消息,发布后将变更标志位置位False
    }
}

编写主方法,按下启动键 

public class Test {
	public static void main(String[] args) {
		Button b = new Button();
		new Machine1(b);
		new Machine2(b);
		System.out.println("启动所有机器");
		b.notifyMachine();
	}
}
启动所有机器
Machine2接收指令:发出启动指令
Machine2已启动
Machine1接收指令:发出启动指令
Machine1已启动

工厂模式

一、简单工厂方法:

以视频工厂为例,输入视频类型,自动生产合适的对象

//创建父抽象类Video,定义抽象方法getDetail
public abstract class Video {
	public abstract void detail();
}

//创建avi类
public class AVI extends Video{
	public void detail() {
		System.out.println("这是avi视频");
	}
}

//创建MP4类
public class MP4 extends Video{
	public void detail() {
		System.out.println("这是mp4视频");
	}
}

//创建rmvb类
public class RMVB extends Video {
	public void detail() {
		System.out.println("这是rmvb视频");
	}
}

创建工厂

public class VideoFactory {
	public static Video getVideo(String type) {
		if("mp4".equals(type)) {
			return new MP4();
		}
		else if("rmvb".equals(type)) {
			return new RMVB();
		}
		else if("avi".equals(type)) {
			return new AVI();
		}else {
			return null;
		}
	}
}

创建测试类

public class Test {
	public static void main(String[] args) {
		VideoFactory.getVideo("mp4").detail();
		Video video = VideoFactory.getVideo("avi");
		video.detail();
	}
}

结果
这是mp4视频
这是avi视频

二、工厂方法

基于开放关闭原则,对扩展的类创建保持开发,所以将创建类的功能下放到具体视频的工厂方法中。例如:

先创建对应的视频类

public abstract class Video {
	public abstract void detail();
}

public class AVI extends Video{
	public void detail() {
		System.out.println("这是avi视频");
	}
}

public class MP4 extends Video{
	public void detail() {
		System.out.println("这是mp4视频");
	}
}

public class RMVB extends Video {
	public void detail() {
		System.out.println("这是rmvb视频");
	}
}

再创建对应的视频类工厂

public interface VideoFactory {
	public Video getVideo();
}

public class AVIFactory implements VideoFactory{
	@Override
	public Video getVideo() {
		return new AVI();
	}
}

public class MP4Factory implements VideoFactory{
	@Override
	public Video getVideo() {
		return new MP4();
	}
}

public class RMVBFactory implements VideoFactory{
	@Override
	public Video getVideo() {
		return new RMVB();
	}
}

最终我们的测试方法:

public class Test {
	public static void main(String[] args) {

		VideoFactory aviFactory = new AVIFactory();
		aviFactory.getVideo().detail();
		VideoFactory mp4Factory = new MP4Factory();
		mp4Factory.getVideo().detail();
		VideoFactory rmvbFactory = new RMVBFactory();
		rmvbFactory.getVideo().detail();
	}
}

这是avi视频
这是mp4视频
这是rmvb视频

三、抽象工厂方法:

所谓抽象工厂,说白了就是当你需要的对象属于不同的类型,但是属于同一家族的时候,我们使用抽象工厂来创建。比如说我们创建一个播放器类,它需要视频文件和字幕文件,那么视频文件和字幕文件又会对应不同的格式,比如mp4啊avi啊之类的。这个时候工厂方式很难满足我们的需求。

所以不妨,我们以播放器为主体,每一个格式类型的播放器对应一套视频+字幕。

//首先编写视频类抽象类和字幕类抽象类
public interface SRT {
	public void getDetail();
}

public interface Video {
	public void getDetail();
}


//其次编写播放器抽象工厂
public interface PlayerFactory {
	//视频
	public Video getVideo();
	//字幕
	public SRT getSRT();
}

 接下来针对不同格式的视频和字幕编写实现类

//接下来针对不同格式的视频和字幕编写实现类
public class AVISRT implements SRT{
	public void getDetail() {
		System.out.println("这是avi字幕");
	}
}
public class AVIVideo implements Video{
	public void getDetail() {
		System.out.println("这是avi视频");
	}
}
public class MP4SRT implements SRT{
	public void getDetail() {
		System.out.println("这是mp4字幕");
	}
}
public class MP4Video implements Video{
	public void getDetail() {
		System.out.println("这是mp4视频");
	}
}

最后编写相关类型格式的播放器工厂 

//最后编写相关类型格式的播放器工厂
public class MP4PlayerFactory implements PlayerFactory {

	@Override
	public Video getVideo() {
		return new MP4Video();
	}

	@Override
	public SRT getSRT() {
		return new MP4SRT();
	}

}

public class AVIPlayerFactory implements PlayerFactory {

	@Override
	public Video getVideo() {
		return new AVIVideo();
	}

	@Override
	public SRT getSRT() {
		return new AVISRT();
	}

}

测试类:

public class Test {
	public static void main(String[] args) {
		PlayerFactory pf = new AVIPlayerFactory();
		Video v = pf.getVideo();
		SRT s = pf.getSRT();
		v.getDetail();
		s.getDetail();
	}
}

这是avi视频
这是avi字幕

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值