【设计模式二之Builder模式】设计模式的Builder模式[结合使用Android中的MediaRecorder来浅析]

设计模式的Builder模式[结合使用Android中的MediaRecorder来浅析]


##摘要:
java23种设计模式之一,英文叫Builder Pattern。其核心思想是将一个“复杂对象的构建算法”与它的“部件及组装方式”分离,使得构件算法和组装方式可以独立应对变化;复用同样的构建算法可以创建不同的表示,不同的构建过程可以复用相同的部件组装方式。

##友情提示:
本文为笔者自己理解,如有写的不对的地方,欢迎指出

版权申明
本文原创作者:章飞_906285288
作者的博客:http://blog.csdn.net/qq_29924041
转载请注明出处


##使用Builder模式来构建我们的MediaRecorder的参数对象
简述:

在Android的开发过程中,无处不见的builder模式,如系统的Dialog的时候采用的就是Builder模式,ImageLoader的初始化的过程中,同样也是。那什么是Builder模式呢?Builder模式又叫做构建者模式。举个最简单的例子:车子是由轮胎,底盘,发动机,方向盘,座椅等组成的。车子是一个类class,具体这些可以组装成奔驰车子,宝马车子等等。不同的参数可以组装成不同的车子。这就是Builder组装的对象。其核心思想是将一个“复杂对象的构建算法”与它的“部件及组装方式”分离,使得构件算法和组装方式可以独立应对变化;复用同样的构建算法可以创建不同的表示,不同的构建过程可以复用相同的部件组装方式。

以下代码是写的是一个Test代码。格式上面没有单独抽出来,MediaRecorder是通过构造一个Params的对象来进行实现的

package com.zzf.cit;

import android.hardware.Camera;
import android.media.MediaRecorder;
import android.view.SurfaceHolder;

import com.eques.cit.util.ELog;

import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

public class VideoRecorder {

	public static final String TAG = "VideoRecorder";
	
	public static final String ROOT_PATH = "/mnt/sdcard/zzf/record";
	
	private static VideoRecorder instance;
	
	private Params mParams;
	private MediaRecorder mMediaRecorder;
	private boolean isRecording = false;
	
	public static VideoRecorder getInstance(){
		if (instance == null) {
			synchronized (VideoRecorder.class) {
				if (instance == null) {
					instance = new VideoRecorder();
				}
			}
		}
		return instance;
	}
	
	public void setParams(Params mParams){
		this.mParams = mParams;
	}
	
	/**
	 * 创建一个私有的无参的构造函数
	 */
	private VideoRecorder(){
		File file = new File(ROOT_PATH);
		if (!file.exists()) {
			file.mkdir();
		}
	}
	
	/**
	 * 开始进行录像
	 */
	public void startRecord(){
		if (!isRecording){
			mMediaRecorder = new MediaRecorder();
			mMediaRecorder.reset();
			if (mParams.mCamera != null) {
				mParams.mCamera.unlock();
			}
			mMediaRecorder.setCamera(mParams.mCamera);
			mMediaRecorder.setAudioSource(mParams.audioSource);
			ELog.i(TAG,"mMediaRecorder.getMaxAmplitude:"+mMediaRecorder.getMaxAmplitude());
			mMediaRecorder.setVideoSource(mParams.videoSource);
			mMediaRecorder.setOutputFormat(mParams.outputFormat);
			mMediaRecorder.setAudioEncoder(mParams.audioEncoderType);
			mMediaRecorder.setVideoEncoder(mParams.videoEncoderType);
			mMediaRecorder.setVideoFrameRate(mParams.videoFrameRate);
			mMediaRecorder.setPreviewDisplay(mParams.mSurfaceHolder.getSurface());
			mMediaRecorder.setVideoSize(mParams.mVideoSize.width, mParams.mVideoSize.height);
			mMediaRecorder.setOutputFile(mParams.recorderPath);
			mMediaRecorder.setVideoEncodingBitRate(300 * 1024 * 5);
			mMediaRecorder.setMaxDuration(60 * 1000);
			mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
				@Override
				public void onInfo(MediaRecorder mr, int what, int extra) {

				}
			});
			Timer timer = new Timer();
			TimerTask timerTask = new TimerTask() {
				@Override
				public void run() {
					if (isRecording){
						isRecording = false;
					}
				}
			};
			timer.schedule(timerTask,60 * 1000);
			try {
				mMediaRecorder.prepare();
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			mMediaRecorder.start();
			isRecording = true;
		}
	}
	
	
	/**
	 * 停止录像
	 */
	public void stopRecord(){
		if (isRecording) {
			isRecording = false;
			if (mMediaRecorder != null) {
				if (mParams.mCamera != null) {
					mParams.mCamera.lock();
				}
				mMediaRecorder.stop();
				mMediaRecorder.release();
				mMediaRecorder = null;

			}
		}
	}
	
}



class Params{
	//录像的具体路径
	public String recorderPath;
	//音频音源
	public int audioSource;
	//视频源
	public int videoSource;
	//输出的格式
	public int outputFormat;
	//音频的编码类型
	public int audioEncoderType;
	//视频的编码类型
	public int videoEncoderType;
	public SurfaceHolder mSurfaceHolder;
	//视频的帧率
	public int videoFrameRate;
	//视频的大小
	public VideoSize mVideoSize;
	//
	public Camera mCamera;
	
	static class VideoSize{
		public int width;
		public int height;
		
		public VideoSize(int width,int height){
			this.width = width;
			this.height = height;
		}
	}
	
	public Params(Builder mBuilder){
		this.recorderPath = mBuilder.recorderPath;
		this.audioSource = mBuilder.audioSource;
		this.videoSource = mBuilder.videoSource;
		this.outputFormat = mBuilder.outputFormat;
		this.audioEncoderType = mBuilder.audioEncoderType;
		this.videoEncoderType = mBuilder.videoEncoderType;
		this.mSurfaceHolder = mBuilder.mSurfaceHolder;
		this.videoFrameRate = mBuilder.videoFrameRate;
		this.mVideoSize =mBuilder.mVideoSize;
		this.mCamera = mBuilder.mCamera;
	}
	
	
	static class Builder{
		//录像的具体路径
		public String recorderPath;
		//音频音源
		public int audioSource = MediaRecorder.AudioSource.MIC ;
		//视频源
		public int videoSource = MediaRecorder.VideoSource.CAMERA;
		//输出的格式
		public int outputFormat = MediaRecorder.OutputFormat.MPEG_4;
		//音频的编码类型
		public int audioEncoderType = MediaRecorder.AudioEncoder.AMR_NB;
		//视频的编码类型
		public int videoEncoderType = MediaRecorder.VideoEncoder.H264;
		
		public SurfaceHolder mSurfaceHolder;
		//视频的帧率
		public int videoFrameRate;
		//视频的大小
		public VideoSize mVideoSize;
		
		public Camera mCamera;

		public Builder(){
			
		}
		
		public Builder recorderPath(String recorderPath){
			this.recorderPath = recorderPath;
			return this;
		}
		
		public Builder audioSource(int audioSource){
			this.audioSource = audioSource;
			return this;
		}
		
		public Builder videoSource(int videoSource){
			this.videoSource = videoSource;
			return this;
		}
		
		public Builder outputFormat(int outputFormat){
			this.outputFormat = outputFormat;
			return this;
		}
		
		public Builder audioEncoderType(int audioEncoderType){
			this.audioEncoderType = audioEncoderType;
			return this;
		}
		
		public Builder videoEncoderType(int videoEncoderType){
			this.videoEncoderType = videoEncoderType;
			return this;
		}
		
		public Builder mSurfaceHolder(SurfaceHolder mSurfaceHolder){
			this.mSurfaceHolder = mSurfaceHolder;
			return this;
		}
		
		public Builder videoFrameRate(int videoFrameRate){
			this.videoFrameRate = videoFrameRate;
			return this;
		}
		
		public Builder mCamera(Camera mCamera){
			this.mCamera = mCamera;
			return this;
		}
		
		public Builder mVideoSize(VideoSize mVideoSize){
			if (mVideoSize != null) {
				this.mVideoSize = mVideoSize;
			}else{
				this.mVideoSize  = new VideoSize(854, 480);
			}
			return this;
		}
		
		public Params build(){
			return new Params(this);
		}
	}

	@Override
	public String toString() {
		return "Params{" +
				"recorderPath='" + recorderPath + '\'' +
				", audioSource=" + audioSource +
				", videoSource=" + videoSource +
				", outputFormat=" + outputFormat +
				", audioEncoderType=" + audioEncoderType +
				", videoEncoderType=" + videoEncoderType +
				", mSurfaceHolder=" + mSurfaceHolder +
				", videoFrameRate=" + videoFrameRate +
				", mVideoSize=" + mVideoSize +
				", mCamera=" + mCamera +
				'}';
	}
}

调用部分的代码,只截取部分的代码。

if (mVideoRecorder != null) {
				Params mParams = new Params.Builder()
						.recorderPath(VideoRecorder.ROOT_PATH + File.separator + new SimpleDateFormat("yyyyMMddHHmmssSSS").format(System.currentTimeMillis())+".3gp")
						.mSurfaceHolder(mSurfaceView.getHolder())
						.audioSource(MediaRecorder.AudioSource.CAMCORDER)
						.audioEncoderType(MediaRecorder.AudioEncoder.AAC)
						.videoSource(MediaRecorder.VideoSource.CAMERA)
						.videoEncoderType(MediaRecorder.VideoEncoder.H263)
						.mVideoSize(new VideoSize(854, 480))
						.videoFrameRate(30)
						.outputFormat(MediaRecorder.OutputFormat.MPEG_4)
						.mCamera(mCamera)
						.build();

				Log.i(TAG,"PARAMS:"+mParams.toString());
				mVideoRecorder.setParams(mParams);
				mVideoRecorder.startRecord();
				}

当然在使用MediaRecorder时候,在Android中是要有权限限制的

   
   
  

Builder模式好处和优点

使用Builder模式必然会导致写两遍相关属性的代码和SETTER方法,看起来有点吃力不讨好。然而需要看到的是,客户端代码的可用性和可读性得到了大大提高。与此同时,构造函数的参数数量明显减少调用起来非常直观。

Builder方法另外一个优势在于,单个builder构建多个对象时Builder参数可在创建期间进行调整,还可以根据对象不同而进行改变。这就像我越来越推崇的以“不变”应“万变”。Builder模式特别适合那些属性个数很多的类,我认为没有必要给那些本不需要设置值传递参数(设置null)。

你可能感兴趣的:(Android学习,Java设计模式学习,java设计模式,android,设计模式,构造者模式,media)