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]
    点灯。。。
    



  • 相关阅读:
    react ts axios 配置跨域
    npm run eject“Remove untracked files, stash or commit any changes, and try again.”错误
    java 进程的参数和list的线程安全
    帆软报表 大屏列表跑马灯效果JS
    帆软报表 快速复用数据集,避免重复劳动
    分析云 OA中部门分级思路和实现方法
    分析云 分段器 只显示一个块的数据
    分析云 更改服务默认的端口号
    分析云U8项目配置方法新版本(2)
    Oracle 创建时间维度表并更新是否工作日字段
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275543.html
Copyright © 2011-2022 走看看