设计模式之单例模式、命令模式浅析

  
/**
 * 单例模式:
 *   确保类只有一个实例,并提供一个全局的访问点
 * 
 * 经典的单例模式
 * 1、将构造器私有化
 * 2、提供一个私有的类的对象的静态成员变量
 * 3、提供一个静态的公有的获取对象的方法
 * 
 * 经典单例模式中 存在一个问题 当在多线程的环境中 可能会有多个ClassicSingleton的对象
 * 当然 可以在getInstance上加上synchronized 同步锁 但是每一次getInstance()的时候
 * 都需要同步 这样会极大地降低性能
 * 所以 查看另外两种变化体
 * 1、急切加载--在构建静态的实例变量时即初始化(不好之处在于,如果此类不使用的话,就浪费资源了)
 * 2、采用双重检查加锁的单例模式 既能够保证延迟实例化对象 又能不影响性能 此种方式最好
 * @author Administrator
 *
 */


下面分别是三种单例模式的构建方式 

经典模式

package com.undergrowth.singleton;

/**
 * 单例模式:
 *   确保类只有一个实例,并提供一个全局的访问点
 * 
 * 经典的单例模式
 * 1、将构造器私有化
 * 2、提供一个私有的类的对象的静态成员变量
 * 3、提供一个静态的公有的获取对象的方法
 * 
 * 经典单例模式中 存在一个问题 当在多线程的环境中 可能会有多个ClassicSingleton的对象
 * 当然 可以在getInstance上加上synchronized 同步锁 但是每一次getInstance()的时候
 * 都需要同步 这样会极大地降低性能
 * 所以 查看另外两种变化体
 * 1、急切加载--在构建静态的实例变量时即初始化(不好之处在于,如果此类不使用的话,就浪费资源了)
 * 2、采用双重检查加锁的单例模式 既能够保证延迟实例化对象 又能不影响性能 此种方式最好
 * @author Administrator
 *
 */
public class ClassicSingleton implements Singleton {

	private ClassicSingleton(){
		System.out.println("构建单例模式对象"+ClassicSingleton.class.getName());
	}
	private static Singleton classicSingleton=null;
	public static  Singleton getInstance(){
		if(classicSingleton==null) {
			classicSingleton=new ClassicSingleton();
			
		}
		return classicSingleton;
	}
	
	/* (non-Javadoc)
	 * @see com.undergrowth.singleton.Singleton#saySomeThing()
	 */
	@Override
	public void saySomeThing(){
		System.out.println("我叫"+classicSingleton.getClass().getName()+",我是单例模式");
	}
}

急切加载模式

package com.undergrowth.singleton;
/**
 * 急切加载--在构建静态的实例变量时即初始化(不好之处在于,如果此类不使用的话,就浪费资源了)
 * @author Administrator
 *
 */
public class EagerSingleton implements Singleton {
   private EagerSingleton(){
	   System.out.println("构建单例模式对象"+EagerSingleton.class.getName());
   }
   /**
    * 构建静态变量时 即初始化对象
    */
   private static EagerSingleton eagerSingleton=new EagerSingleton();
   public static EagerSingleton getInstance(){
	   return eagerSingleton;
   }
   public void saySomeThing(){
		System.out.println("我叫"+eagerSingleton.getClass().getName()+",我是单例模式");
	}
}

双重检查加锁模式

package com.undergrowth.singleton;
/**
 * 采用双重检查加锁的单例模式 既能够保证延迟实例化对象 又能不影响性能 此种方式最好
 * @author Administrator
 *
 */
public class DoubleCheckedLockSingleton implements Singleton {

	private DoubleCheckedLockSingleton(){
		 System.out.println("构建单例模式对象"+DoubleCheckedLockSingleton.class.getName());
	}
	/**
	 * volatile关键字保证在多个线程中 获取到正确的doubleCheckedLockSingleton值
	 */
	private static volatile DoubleCheckedLockSingleton doubleCheckedLockSingleton=null;
	public static DoubleCheckedLockSingleton getInstance(){
		if(doubleCheckedLockSingleton==null){
			synchronized (DoubleCheckedLockSingleton.class) {
				if(doubleCheckedLockSingleton==null) doubleCheckedLockSingleton=new DoubleCheckedLockSingleton();
			}
			
		}
		return doubleCheckedLockSingleton;
	}
	@Override
	public void saySomeThing() {
		System.out.println("我叫"+doubleCheckedLockSingleton.getClass().getName()+",我是单例模式");
	}
	
}

单例接口

package com.undergrowth.singleton;

public interface Singleton {

	public abstract void saySomeThing();

}

单例测试

package com.undergrowth.singleton.test;

import static org.junit.Assert.*;

import org.junit.Test;

import com.undergrowth.singleton.ClassicSingleton;
import com.undergrowth.singleton.DoubleCheckedLockSingleton;
import com.undergrowth.singleton.EagerSingleton;
import com.undergrowth.singleton.Singleton;

public class SingletonTest {

	@Test
	public void test() {
		final Singleton singleton;
		//经典单例模式
		for(int i=0;i<10;i++){
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					// TODO Auto-generated method stub
					ClassicSingleton.getInstance().saySomeThing();
				}
			}).run();
			
		}
		
		//急切模式
		for(int i=0;i<10;i++){
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					// TODO Auto-generated method stub
					EagerSingleton.getInstance().saySomeThing();
				}
			}).run();
			
		}
		
		//双重检查加锁模式
				for(int i=0;i<10;i++){
					new Thread(new Runnable() {
						
						@Override
						public void run() {
							// TODO Auto-generated method stub
							DoubleCheckedLockSingleton.getInstance().saySomeThing();
						}
					}).run();
					
				}
		
		
	}

}

输出

构建单例模式对象com.undergrowth.singleton.ClassicSingleton
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
我叫com.undergrowth.singleton.ClassicSingleton,我是单例模式
构建单例模式对象com.undergrowth.singleton.EagerSingleton
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
我叫com.undergrowth.singleton.EagerSingleton,我是单例模式
构建单例模式对象com.undergrowth.singleton.DoubleCheckedLockSingleton
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式
我叫com.undergrowth.singleton.DoubleCheckedLockSingleton,我是单例模式

2、命令模式

/**
 * 命令模式
 *   将请求封装成对象,使不同的请求、日志、队列来参数化其他对象。
 *   
 *  说实话,这个命令模式的定义真的不好懂 
 * 
 * 简单点说:命令模式可以将发起请求的调用者和接收执行请求的对象解耦
 * 原因在于:命令对象中包括了接收者和执行动作
 *    当调用者接收到命令对象后,调用命令对象中的方法,由命令对象找到接收者进而执行相关的操作
 * 
 * 按照聪明程度 将命令对象划分为:
 *   糊涂的命令对象--只是负责转发调用者的请求,由接收者完成相关的操作
 *   聪明的命令对象--将接收者的处理操作也做了
 *   当然 为了更好的解耦 我们推荐糊涂的命令对象
 *    
 * 实例:
 *   采用遥控器 控制点灯、热水器的开关
 *   遥控器即是调用者 点灯的行为与接收者灯封装在命令对象中
 * 
 * @author Administrator
 *
 */


先看调用者 遥控器

package com.undergrowth.command;

import java.util.Arrays;

/**
 * 命令模式
 *   将请求封装成对象,使不同的请求、日志、队列来参数化其他对象。
 *   
 *  说实话,这个命令模式的定义真的不好懂 
 * 
 * 简单点说:命令模式可以将发起请求的调用者和接收执行请求的对象解耦
 * 原因在于:命令对象中包括了接收者和执行动作
 *    当调用者接收到命令对象后,调用命令对象中的方法,由命令对象找到接收者进而执行相关的操作
 * 
 * 按照聪明程度 将命令对象划分为:
 *   糊涂的命令对象--只是负责转发调用者的请求,由接收者完成相关的操作
 *   聪明的命令对象--将接收者的处理操作也做了
 *   当然 为了更好的解耦 我们推荐糊涂的命令对象
 *    
 * 实例:
 *   采用遥控器 控制点灯、热水器的开关
 *   遥控器即是调用者 点灯的行为与接收者灯封装在命令对象中
 * 
 * @author Administrator
 *
 */
public class RemoteControl {
   
	private final int num=2;
	
	Command[] commandOns=new Command[num];
	Command[] commandOffs=new Command[num];
	Command lastCommand=null;
	
	public RemoteControl(){
		NoCommand noCommand=new NoCommand();
		for(int i=0;i<num;i++)
		{
			commandOns[i]=noCommand;
			commandOffs[i]=noCommand;
		}
	}
	
	public void setCommand(int position,Command commandOn,Command commandOff) {
		commandOns[position]=commandOn;
		commandOffs[position]=commandOff;
	}
	
	public void buttonOnWasPress(int position){
		commandOns[position].execute();
		lastCommand=commandOns[position];
	}
	
	public void buttonOffWasPress(int position){
		commandOffs[position].execute();
		lastCommand=commandOffs[position];
	}
	
	public void cancel()
	{
		lastCommand.undo();
	}

	
	@Override
	public String toString() {
		return "RemoteControl [num=" + num + ", commandOns="
				+ Arrays.toString(commandOns) + ", commandOffs="
				+ Arrays.toString(commandOffs) + ", lastCommand=" + lastCommand
				+ "]";
	}
	
	
	
}

再看命令对象接口

package com.undergrowth.command;
/**
 * 命令对象接口
 * @author Administrator
 *
 */
public interface Command {
	public void execute();
	public void undo();
}


接着是 灯的命令对象

package com.undergrowth.command;

public class LightOnCommand implements Command {

	Light light;
	
	public LightOnCommand(Light light){
		this.light=light;
	}
	
	@Override
	public void execute() {
		// TODO Auto-generated method stub
		light.on();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		light.off();
	}

}

package com.undergrowth.command;

public class LightOffCommand implements Command {

	Light light;

	public LightOffCommand(Light light) {
		this.light = light;
	}

	@Override
	public void execute() {
		// TODO Auto-generated method stub
		light.off();
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		light.on();
	}

}


空命令对象

package com.undergrowth.command;

/**
 * 空命令对象 什么也不操作 仅仅用于初始化
 * @author Administrator
 *
 */
public class NoCommand implements Command {

	@Override
	public void execute() {
		// TODO Auto-generated method stub

	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub

	}

}

接收者 灯

package com.undergrowth.command;

public class Light {
	
	public void on(){
		System.out.println("点灯。。。");
	}
	
	public void off(){
		System.out.println("关灯。。。");
	}
	
}

测试

package com.undergrowth.command.test;

import static org.junit.Assert.*;

import org.junit.Test;

import com.undergrowth.command.Light;
import com.undergrowth.command.LightOffCommand;
import com.undergrowth.command.LightOnCommand;
import com.undergrowth.command.RemoteControl;

public class RemoteControlTest {

	@Test
	public void test() {
		RemoteControl control=new RemoteControl();
		Light light=new Light();
		LightOnCommand lightOnCommand=new LightOnCommand(light);
		LightOffCommand lightOffCommand=new LightOffCommand(light);
		control.setCommand(0, lightOnCommand, lightOffCommand);
		System.out.println(control);
		control.buttonOnWasPress(0);
		control.buttonOffWasPress(0);
		System.out.println(control);
		control.cancel();
		
	}

}
结果

RemoteControl [num=2, commandOns=[com.undergrowth.command.LightOnCommand@4391f0, com.undergrowth.command.NoCommand@2250d5], commandOffs=[com.undergrowth.command.LightOffCommand@e8eeca, com.undergrowth.command.NoCommand@2250d5], lastCommand=null]
点灯。。。
关灯。。。
RemoteControl [num=2, commandOns=[com.undergrowth.command.LightOnCommand@4391f0, com.undergrowth.command.NoCommand@2250d5], commandOffs=[com.undergrowth.command.LightOffCommand@e8eeca, com.undergrowth.command.NoCommand@2250d5], lastCommand=com.undergrowth.command.LightOffCommand@e8eeca]
点灯。。。



posted on 2014-12-04 23:40  liangxinzhi  阅读(178)  评论(0编辑  收藏  举报