设计模式之单例模式、命令模式浅析
/** * 单例模式: * 确保类只有一个实例,并提供一个全局的访问点 * * 经典的单例模式 * 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 阅读(184) 评论(0) 收藏 举报
浙公网安备 33010602011771号