用户操作
[即时聊天] [发私信] [加为好友]
刘晓伟ID:lxwde
167987次访问,排名457好友0人,关注者2
lxwde的文章
原创 27 篇
翻译 34 篇
转载 0 篇
评论 243 篇
最近评论
sankecong369:那里能下载呀
lshvs2006:你好,你設計的東東非常不錯。
但是,現在有個疑問,不知道,怎樣保存設計的文件,
存成XML 文件格式可能會好一點,但是,不知道如何去存? 需要調用什么接口 或是 需要寫什么 方法嗎?

期待您的指教。謝謝

lsh2011@163.com
zeeler:补上这一部分吧(本人中文表述能力没有lxwde强哦 :) ):
The Singleton
也许最简单的设计模式是Singleton模式了,它可以给某种类型提供唯一的对象,下面是个例子:
(译者按:例子省略)
创建一个唯一对象的关键是防止客户程序员(client programmer)用其他任意方法创建对象,只能用你提供的方法。你必须把所有构造器写成p……
zeeler:翻译的不错呀,全力支持!
不过在Design principles和Classifying patterns之间还有个The Singleton部分好像lxwde漏掉了?还是Bruce Eckel修改版面了?
总之,支持呀,本来我也想翻译一下的,不过没有lxwde这么有毅力,翻译一节就停了,实在很累的,所以非常敬佩lxwde能坚持做这么多!
roger_77:可惜,
这个库被boost放弃了,加入另一个ASIO的网络类库
文章分类
收藏
    相册
    链接
    My articles on codeproject
    SharpFormEditor下载
    Thinking in Patterns中文版
    友情链接
    alai04
    C++的罗浮宫
    fatalerror99
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 使用Interpreter和Visitor模式进行条件解析收藏

    新一篇: Erich Gamma: 如何使用设计模式 | 旧一篇: 金额数字到中文大写的转换--C++代码

    从以前同事代码里学到的一个,比较好玩。节前写在CodeProject上,应该算是关于模式的,不知道CodeProject的编辑为什么给归类到Parser去了。

    http://www.codeproject.com/cpp/ConditionInterpreter.asp

    Introduction

    This article gives a flexible and simple (maybe not that simple) method to do condition parsing. It also shows the usage of the visitor pattern and the interpreter pattern.

    In the example of this article, we define the properties of a desired person as: (NAME='test' AND GENDER='M' AND HEIGHT>100 AND WEIGHT<1000). For a given person whose properties are (NAME='test' AND GENDER='M' AND HEIGHT=101 AND WEIGHT=888), when evaluated by the criteria defined above, the result will be 'is a desired person' because 101>100 and 888<1000; if we change the person's NAME to 'test1' or GENDER to 'F' or HEIGHT to '99', the result will be 'not a desired person'.

    The classes

    CMetaCondition defines a tstring value (m_tsValue) as a data member and some operations to compare a given value with m_tsValue, those operations are EQUAL, NOT_EQUAL, GREATER_THAN, LESS_THAN, CONTAINS, NOT_CONTAINS. You may expand these operations as you wish.

    class CMetaCondition 
    {
    public:
           enum KeyValueOp {KEYVALUE_OP_EQUAL, KEYVALUE_OP_NOT_EQUAL,
                           KEYVALUE_OP_GREATER_THAN, KEYVALUE_OP_LESS_THAN,
                           KEYVALUE_OP_CONTAINS, KEYVALUE_OP_NOT_CONTAINS};
    public:
           int m_iKey;
           KeyValueOp m_op;
           tstring m_tsValue;...
    };

    CCondition has a data member m_conditions, which is a vector of sub conditions. When evaluated, if the condition operation(m_op) of a CCondition object is META, the m_metaCondition field will take effect, otherwise, AND or OR will be applied on m_conditions. For an AND operation, if all the sub conditions are true, the result will be true; For an OR operation, if one of the subconditions is true, the result will be true. The code shows this:

    class CCondition
    {
    public:
     enum ConditionOp{CONDITION_OP_AND,CONDITION_OP_OR,CONDITION_OP_META};
    public:
     /*if m_op is CONDITION_AND, or CONDITION_OR,
     the m_conditions field will take effect.
     Otherwise, the m_metaCondition field will take effect.
     */
     ConditionOp m_op;
     vector<CCONDITION> m_conditions;
     CMetaCondition m_metaCondition;
    
    public:
     BOOL IsTrue(CConditionInterpreter* pInterpreter);
    ...
    };

    CConditionInterpreter has only one method: IsTrue(...). You'll see later in this article that when applied with the visitor pattern, this method is just visit(...­) method of the visitor pattern; when applied with the interpreter pattern, this method is better named as interpret(...). Since the two patterns are bound together, the method is named as IsTrue(...­).

    class CConditionInterpreter
    {
    public:
     virtual BOOL IsTrue(CMetaCondition& metaCond) = 0;
    }

    CPersonChooser is derived from CConditionInterpreter, it overrides the virtual method: IsTrue(...), that is where the actual visit and interpreting happens.

    class CPersonChooser : public CConditionInterpreter
    {
    public:
     CPersonChooser(const CPerson& person);
     virtual ~CPersonChooser();
    
     virtual BOOL IsTrue(CMetaCondition& metaCondition);
    private:
     CPerson m_person;
    }

    The following code shows how to use them together:

    //define the desired condition
    m_conditions= predefined_condition;
    ...
    CPerson person;
    person.name="test";
    person.gender="M";
    person.height="101";
    person.weight="888";
    
    //construct a CPersonChooser using
    //the given person's properties
    CPersonChooser* pChooser=new CPersonChooser(person);
    
    //m_condition Accepts a CPersonChooser, then the CPersonChooser
    //visits and interprets the (meta) condition
    BOOL isDesiredPerson=m_condition.IsTrue(pChooser);
    
    CString strInfo=isDesiredPerson?"IS":"NOT";
    strInfo+=" a desired person";
    AfxMessageBox(strInfo);
    
    delete pChooser;

    In the next section, I'll explain how the visitor pattern and the interpreter pattern are applied to these classes.

    The visitor pattern

    The motivation of the visitor pattern is: Represent an operation to be performed on the elements of an object structure.

    In our example, CConditionInterpreter is the Visitor class in the diagram, CPersonChooser is a concrete visitor derived from it, CCondition is an Element class (and also a concrete element class itself).

    The IsTrue(...­) method of CCondition acts as the Accept member function of a normal element class according to the standard visitor pattern. It calls the visit method (CPersonChooser::IsTrue(...­)) of the visitor (pInterpreter) inside its Accept method.

    return pInterpreter->IsTrue(m_metaCondition);

    The interpreter pattern

    The motivation of the interpreter pattern is: Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in a language.

    In our example, CMetaCondition is a Context while CConditionInterpreter is an AbstractExpression, and CPersonChooser is a TerminalExpression.

    The IsTrue(...) method of CConditionInterpreter and CPersonChooser acts as the Interpret(in Context) member function of a normal XXXExpression class according to the standard interpreter pattern, that is where the actual interpreting happens.

    public:
           virtual BOOL IsTrue(CMetaCondition& metaCondition);
           // this member function acts as Interpret(in Context) of a normal 
           // Expression class

    The code

    //The Accept method of the visitor pattern
    BOOL CCondition::IsTrue(CConditionInterpreter* pInterpreter)
    {       if (m_op == CONDITION_OP_AND) {
                  if (m_conditions.size() == 0)
                         return FALSE;
                  BOOL bAndCondIsTrue = TRUE;
                  for (vector<CCondition>::iterator it = m_conditions.begin(); 
                it != m_conditions.end(); it++) {
                         if (!(*it).IsTrue(pInterpreter)) {
                                bAndCondIsTrue = FALSE;
                                break;
                         }
                  }
                  return bAndCondIsTrue;
           }
           if (m_op == CONDITION_OP_OR) {
                  if (m_conditions.size() == 0)
                         return FALSE;
                  BOOL bOrCondIsTrue = FALSE;
                  for (vector<CCondition>::iterator it = m_conditions.begin(); 
                       it != m_conditions.end(); it++)  {
                         if ((*it).IsTrue(pInterpreter)) {
                                bOrCondIsTrue = TRUE;
                                break;
                         }
                  }
                  return bOrCondIsTrue;       
           }
           return pInterpreter->IsTrue(m_metaCondition);
    }
    //...
    //The Visit method of the visitor pattern and Interpret method of
    //the interpreter pattern
    BOOL CPersonChooser::IsTrue(CMetaCondition& metaCondition)
    {
           switch (metaCondition.m_iKey) {
           case KEY_NAME:
                  switch(metaCondition.m_op) {
                  case metaCondition.KEYVALUE_OP_EQUAL:
                      return (m_person.name == metaCondition.m_tsValue);
                  case metaCondition.KEYVALUE_OP_NOT_EQUAL:
                      return (m_person.name != metaCondition.m_tsValue);
                  case metaCondition.KEYVALUE_OP_GREATER_THAN:
                      return (m_person.name > metaCondition.m_tsValue);
                  case metaCondition.KEYVALUE_OP_LESS_THAN:
                      return (m_person.name < metaCondition.m_tsValue);
                  default:
                      break;
                  }
                  break;
           case KEY_GENDER:
                  switch(metaCondition.m_op) {
                  case metaCondition.KEYVALUE_OP_EQUAL:
                      return (m_person.gender == metaCondition.m_tsValue);
                  case metaCondition.KEYVALUE_OP_NOT_EQUAL:
                      return (m_person.gender != metaCondition.m_tsValue);
                  default:
                      break;
                  }
                  break;
           case KEY_HEIGHT:
                  switch(metaCondition.m_op) {
                  case metaCondition.KEYVALUE_OP_EQUAL:
                     return (m_person.height == 
                              atoi(metaCondition.m_tsValue.c_str()));
                  case metaCondition.KEYVALUE_OP_NOT_EQUAL:
                     return (m_person.height != 
                              atoi(metaCondition.m_tsValue.c_str()));
                  case metaCondition.KEYVALUE_OP_GREATER_THAN:
                     return (m_person.height > 
                              atoi(metaCondition.m_tsValue.c_str()));
                  case metaCondition.KEYVALUE_OP_LESS_THAN:
                     return (m_person.height < 
                              atoi(metaCondition.m_tsValue.c_str()));
                  default:
                     break;
                  }
                  break;
           case KEY_WEIGHT:
                  switch(metaCondition.m_op) {
                  case metaCondition.KEYVALUE_OP_EQUAL:
                     return (m_person.weight == 
                         atoi(metaCondition.m_tsValue.c_str()));
                  case metaCondition.KEYVALUE_OP_NOT_EQUAL:
                     return (m_person.weight != 
                         atoi(metaCondition.m_tsValue.c_str()));
                  case metaCondition.KEYVALUE_OP_GREATER_THAN:
                     return (m_person.weight > 
                         atoi(metaCondition.m_tsValue.c_str()));
                  case metaCondition.KEYVALUE_OP_LESS_THAN:
                     return (m_person.weight < 
                         atoi(metaCondition.m_tsValue.c_str()));
                  default:
                     break;
                  }
                  break;
           }      
           return FALSE;
    }

    Credits

    • I learned the usage of this idiom from my co-worker Alvin Robin Shen. He is a real programmer and a very nice guy. I used to get the opportunity to write the condition configuration module for him during our project development and all the classes presented in this article are copied from him. Now he is busy with his open source project: Luntbuild.
    • When you look at the downloaded source code, you'll find that I have used a CComboListCtrl as the main UI for condition setting. This class is written by Aravindan Premkumar. You can find the introduction of this control at: Customized Report List Control with In-Place Combo Box & Edit Control.

    发表于 @ 2005年05月07日 18:12:00|评论(loading...)|编辑

    新一篇: Erich Gamma: 如何使用设计模式 | 旧一篇: 金额数字到中文大写的转换--C++代码

    评论:没有评论。

    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © lxwde