Head First 设计方式 Design Pattern 5-6

Head First 设计模式 Design Pattern 5-6

Section 5 单件模式 Singleton

创建独一无二的, 只能有一个实例的对象. 延迟实例化 Lazy Instantiaze

单件模式 确保一个类只有一个实例, 并提供一个全局访问点

Head First 设计方式 Design Pattern 5-6

处理多线程

>Java 利用同步, 缺点是降低性能;   

>Java 利用急切 Eagerly方式创建单件, JVM保证在任何线程访问instance之前先创建实例    

1
public static synchronized Singleton getInstance()
1
2
3
4
5
6
7
public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton();
    public static Singleton getInstance(){
        return instance;
    }
}

>双重检查加锁 double checked locking, Java - volatile, synchronized

>Java 单件模式要避免多个类加载器

1
2
3
4
5
6
7
8
9
10
11
12
13
class Singleton
{
public:
   static Singleton* instance();
   void Print();
private:
    Singleton() {};
    void lockForSync() {};
    void unLockForSync() {};
                                                                                                                    
private:
   static Singleton* mpInstance;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Singleton* Singleton::mpInstance = NULL; //static member must be initialized
                                                                                                               
Singleton* Singleton::instance()
{
    if ( !mpInstance )
    {
        lockForSync();
        if ( !mpInstance )
            mpInstance = new Singleton;
        unLockForSync();
    }
    return mpInstance;
}
                                                                                                               
void Singleton::Print()
{
    cout << "Print the instance" << endl;
}
1
Singleton::instance()->Print();

Summary

>单件模式 确保一个类只有一个实例, 并提供全局访问点

>要点  确保程序中一个类只有一个实例; 提供访问这个实例的全局点; 私有构造器, 静态方法, 静态变量; 多线程问题; 双重检查加锁;

Java避免多个JVM加载器产生多个实例; Java单件注册表; 

GlobalAccessPoint, DoubleChecked, Lazy, Private, ClassLoaders, Statically, GarbageCollector, Constructor, MultiThreading, Instance

---Section 5 End---

Section 6 命令模式 Command

封装方法调用 Method Invocation

命令模式 将请求封装成对象, 以便使用不同的请求, 队列或者日志来参数化其他对象. 支持可撤销的操作.

Head First 设计方式 Design Pattern 5-6

>Client创建一个ConcereteCommand, 设置Receiver; Invoke持有一个Command对象, 可调用execute方法执行请求; Command为所有命令声明了接口, 调用

命令对象的execute()方法, 让接收者进行相应的操作, 接口也具备undo()方法; 任何类可以作为接收者; ConcreteCommand定义了动作和接收者之间的绑定关系,

调用者通过execute()发出请求, 由ConcreteCommand调用接收者的一个或多个动作.

Party模式 MacrcoCommand, MetaCommandPattern

>队列请求 将运算打包, 在不同的线程中调用, example 线程池, 日程安排, 工作队列

>日志请求 store() load(), JAVA 对象序列化 Serialization; 在执行命令时将历史记录储存在磁盘上, 在重新启动时将命令对象重新加载, 依次调用 (持久化 Persistence).

从检查点 checkpoint 开始应用这些操作. 事务处理 Transaction, 一整批操作需必须全部完成, 否则退回原点, 没有做任何操作.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//Command
class ICommand
{
public:
    enum commandType
    {
        TLight = 1,
        TDoor = 2,
    } cmdType;
    virtual void execute() = 0;
    virtual void undo() = 0;
};
typedef map <int, ICommand*> CmdMap;
typedef vector <ICommand*> CmdVec;
     
class NoCommand : public ICommand
{
public:
    NoCommand() {};
    virtual void execute() { cout << "NoCommand" << endl ;};
    virtual void undo() {};
};
     
class Light
{
public:
    void on() { cout << "Light On" << endl; }
    void off() { cout << "Light Off" << endl; }
};
     
class LightOnCommand : public ICommand
{
public:
    LightOnCommand(Light* light);
    virtual void execute();
    virtual void undo();
private:
    Light* mpLight;
};
     
class Door
{
public:
    void open() { cout << "Door Open" << endl; }
    void close() { cout << "Door Close" << endl; }
};
     
class DoorOpenCommand : public ICommand
{
public:
    DoorOpenCommand(Door* door);
    virtual void execute();
    virtual void undo();
private:
    Door* mpDoor;
};
     
class SimpleRemoteControl
{
public:
    SimpleRemoteControl() {};
    void setCommand(ICommand* cmd);
    void buttonPressed();
private:
    ICommand* mpCmdSlot;
};
     
class RemoteControl
{
public:
    RemoteControl();
    void setOnCommand(int id, ICommand* onCmd);
    void ButtonOnPressed(int id);
    void ButtonUndoPressed();
private:
    CmdMap mOnCommands;
    ICommand* undoCommand;
};
     
class MacroCommand : public ICommand
{
public:
    MacroCommand() {};
    void addCommand(ICommand* cmd);
    virtual void execute();
    virtual void undo();
private:
    CmdVec mCommands;
    CmdVec mUndoCmds;
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//Command
LightOnCommand::LightOnCommand(Light* light)
{
    mpLight = light;
}
     
void LightOnCommand::execute()
{
    mpLight->on();
}
     
void LightOnCommand::undo()
{
    mpLight->off();
}
     
void SimpleRemoteControl::setCommand(ICommand* cmd)
{
    mpCmdSlot = cmd;
}
     
void SimpleRemoteControl::buttonPressed()
{
    mpCmdSlot->execute();
}
     
DoorOpenCommand::DoorOpenCommand(Door* door)
{
    mpDoor = door;
}
     
void DoorOpenCommand::execute()
{
    mpDoor->open();
}
     
void DoorOpenCommand::undo()
{
    mpDoor->close();
}
     
RemoteControl::RemoteControl()
{
    undoCommand = new NoCommand();
}
     
void RemoteControl::setOnCommand(int id, ICommand* onCmd)
{
    //mOnCommands.insert(pair<int, ICommand*>(id, onCmd));
    mOnCommands[id] = onCmd;
}
     
void RemoteControl::ButtonOnPressed(int id)
{
    CmdMap::iterator iter = mOnCommands.find(id);
    if (iter != mOnCommands.end())
    {
        ICommand* pCmd = iter->second;
        pCmd->execute();
        undoCommand = pCmd;
    }
    else
        cout << "Command NOT Found" << endl;
}
     
void RemoteControl::ButtonUndoPressed()
{
    undoCommand->undo();
}
     
void MacroCommand::addCommand(ICommand* cmd)
{
    mCommands.push_back(cmd);
}
     
void MacroCommand::execute()
{
    CmdVec::iterator iter = mCommands.begin();
    for (; iter != mCommands.end(); iter++)
    {
        (*iter)->execute();
        mUndoCmds.push_back(*iter);
    }
}
     
void MacroCommand::undo()
{
  while (!mUndoCmds.empty())
  {
    mUndoCmds.back()->undo();
    mUndoCmds.pop_back();
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Command
        SimpleRemoteControl* sRemoteControl = new SimpleRemoteControl();
        Light* light = new Light();
        LightOnCommand* lightOnCmd = new LightOnCommand(light);
        sRemoteControl->setCommand(lightOnCmd);
        sRemoteControl->buttonPressed();
        Door* door = new Door();
        DoorOpenCommand* doorOpenCmd = new DoorOpenCommand(door);
        sRemoteControl->setCommand(doorOpenCmd);
        sRemoteControl->buttonPressed();
            
        RemoteControl* remoteControl = new RemoteControl();
        remoteControl->setOnCommand(ICommand::TLight, lightOnCmd);
        remoteControl->ButtonOnPressed(ICommand::TLight);
        remoteControl->ButtonOnPressed(ICommand::TDoor);
        remoteControl->ButtonUndoPressed();
        MacroCommand* partyoCmd = new MacroCommand();
        partyoCmd->addCommand(doorOpenCmd);
        partyoCmd->addCommand(lightOnCmd);
        partyoCmd->execute();
        partyoCmd->undo();

Summary

>命令模式 将请求封装成对象, 可以使用不同的请求, 队列, 或者日志请求来参数化其他对象, 支持撤消操作. 

>要点 将发出请求的对象和执行请求的对象解耦; 被解耦的两者之间通过命令对象进行沟通, 命令对象封装了接收者的一个或一组动作; 调用者通过调用命令对象的execute()发出请求,

调用接收者的动作; 调用者接受命令当作参数, 可以运行时动态进行; 命令可撤消, 实现undo()来回到执行前状态; 宏命令是命令的简单延伸, 允许调用多个命令, 支持撤消; 聪明命令对象, 

直接实现请求, 代替接收者; 日志和事务系统;

Client, Invoker, Binds, Decoupled, VendorClasses, Execute, Receiver, Command, Undo, Request

---Section 6 End---