zoukankan      html  css  js  c++  java
  • 设计模式之单例模式、命令模式浅析

      
    /**
     * 单例模式:
     *   确保类只有一个实例,并提供一个全局的访问点
     * 
     * 经典的单例模式
     * 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]
    点灯。。。
    



  • 相关阅读:
    PHP json_decode()解析失败 返回NULL 错误是4
    PHP 合并两个二维数组 array_map 和 array_walk 的区别
    PHP二维数组指定字段进行排序
    常用正则汇总
    PHP中json_encode()使用须知,JSON数组和JSON对象
    PHPExcel大文件块级别读取 速度快 减少占用资源
    移动端border-radius失效
    JavaScript滑动页面到顶部
    软键盘把底部div顶上去
    JavaScript滚动div
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275543.html
Copyright © 2011-2022 走看看