设计模式之单例模式、命令模式浅析
/** * 单例模式: * 确保类只有一个实例,并提供一个全局的访问点 * * 经典的单例模式 * 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) 编辑 收藏 举报