WEB开发网
开发学院软件开发VC 单件模式之土著人的可乐瓶 阅读

单件模式之土著人的可乐瓶

 2008-08-09 19:26:13 来源:WEB开发网   
核心提示: 图一 执行结果执行结果跟我们预期的一样,这就是传说中的类单件,单件模式之土著人的可乐瓶(2),土著人A用它来砸地瓜,土著人B用它来吹口哨,请来信告知,参考文献:1.《设计模式-可复用面向对象软件的基础》-- 李英军等译2.《深入浅出设计模式》-- Eric Freeman,我个人对类单件的

图一 执行结果

执行结果跟我们预期的一样,这就是传说中的类单件,土著人A用它来砸地瓜,土著人B用它来吹口哨。我个人对类单件的理解是这样的,类单件是对相似的函数块、功能块或其他模块进行封装,尽量不涉及类的属性。像二进制,十进制,十六进制字符串进行相互转换的函数,如:class CNumFormat
{
private:
  CNumFormat();
public:
  static CString From2TO10(LPCTSTR lpszTxt2);
  static CString From2TO16(LPCTSTR lpszTxt2);
  static CString From10TO2(LPCTSTR lpszTxt2);
  static CString From10TO16(LPCTSTR lpszTxt2);
  static CString From16TO2(LPCTSTR lpszTxt2);
  static CString From16TO10(LPCTSTR lpszTxt2);
};
  在本例子中的CGlassBottle类,这样用也是可以的,但我们还可以把它设计得更好。在《深入浅出设计模式》中是这样定义单件模式的:确保一个类只有一个实例,并提供全局访问点。下面我们根据该定义对CGlassBottle类进行改进:class CGlassBottle 
{
private:
  CGlassBottle();
public:
  virtual ~CGlassBottle();
public:
  bool OnKnock();//砸
  bool OnBlow();//吹
  bool OnRoll();//擀
public:
  static CGlassBottle s_GlassBottle;//定义
protected:
  bool m_bUsed;//是否正在被使用
};
  对土著人A、B类进行相应的修改:class A//土著人A
{
public:
  void UseBottle()
  {
    CGlassBottle::s_GlassBottle.OnKnock();
  };
};
class B//土著人B
{
public:
  void UseBottle()
  {
    CGlassBottle::s_GlassBottle.OnBlow();
  };
};
  很多时候我们不希望s_GlassBottle暴露出来,而更希望通过函数调用来获取,于是增加一个获取s_GlassBottle的函数,同时把GlassBottle搞成私有静态成员,具体如下:class CGlassBottle 
{
private:
  CGlassBottle();
public:
  virtual ~CGlassBottle();
public:
  bool OnKnock();//砸
  bool OnBlow();//吹
  bool OnRoll();//擀
public:
  static CGlassBottle* GetInstance()
  {
    return &s_GlassBottle;
  }
private:
  static CGlassBottle s_GlassBottle;//定义
protected:
  bool m_bUsed;//是否正在被使用
};
  土著人 A、B类在UseBottle()时进行如下修改:class A//土著人A
{
public:
  void UseBottle()
  {
    CGlassBottle::GetInstance()->OnKnock();
  };
};
class B//土著人B
{
public:
  void UseBottle()
  {
    CGlassBottle::GetInstance()->OnBlow();
  };
};
  可能许多朋友都听说过延迟实例化这个概念,那我们这里也玩玩这个概念:  class CGlassBottle 
  {
  private:
    CGlassBottle();
  public:
    virtual ~CGlassBottle();
  public:
    bool OnKnock();//砸
    bool OnBlow();//吹
    bool OnRoll();//擀
  public:
    static CGlassBottle* GetInstance()
    {
      static CGlassBottle s_GlassBottle;//定义
      return &s_GlassBottle;
    }  
  protected:
    bool m_bUsed;//是否正在被使用
};
  其实我也偏好这种用法,不知道在多线程下面会不会有问题(我只在单线程下玩,所以还没有发现过问题)。但是你会发现在调用GetInstance()的时候必须要在前面加上CGlassBottle::,在调用时像下面这样:CGlassBottle::GetInstance()->OnKnock();  这是不是会让人觉得啰嗦呢,至少对我来说很啰嗦,但我们还可以像下面这么处理:#define GetGlassBottle() CGlassBottle::GetInstance()用的时候就这么用“GetGlassBottle()->Knock();”,当然还可以对CGlassBottle进行改进,不知道这叫不叫改进:class CGlassBottle 
{
private:
  CGlassBottle();
public:
  virtual ~CGlassBottle();
public:
  bool OnKnock();//砸
  bool OnBlow();//吹
  bool OnRoll();//擀
private:
  friend CGlassBottle* GetGlassBottle();
  static CGlassBottle* GetInstance()
  {
    static CGlassBottle s_GlassBottle;//定义
    return &s_GlassBottle;
  }  
protected:
  bool m_bUsed;//是否正在被使用
};
inline CGlassBottle* GetGlassBottle()
{
  return CGlassBottle::GetInstance();
}
  现在可以这样用了:GetGlassBottle()->OnKnock();  这样看起来是不是舒服多了。

我这个人比较懒,一直喜欢像下面这样用,因为一直没有出现过问题,所以用得挺爽:class CGlassBottle 
{
private:
  CGlassBottle();
public:
  virtual ~CGlassBottle();
public:
  bool OnKnock();//砸
  bool OnBlow();//吹
  bool OnRoll();//擀
private:
  friend CGlassBottle* GetGlassBottle();  
protected:
  bool m_bUsed;//是否正在被使用
};
inline CGlassBottle* GetGlassBottle()
{
  static CGlassBottle s_GlassBottle;//定义
  return &s_GlassBottle;
}
  文章到此结束,如有不妥之处,请来信告知。

参考文献:

1.《设计模式-可复用面向对象软件的基础》-- 李英军等译

2.《深入浅出设计模式》-- Eric Freeman,Elisabeth Freeman,^Kathy Sierra & Bert Bates著

上一页  1 2 

Tags:单件 模式 土著人

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接