编程思绪,06-6-16 到 06-11-23

来源:互联网 发布:淘宝网天猫帽子 编辑:程序博客网 时间:2024/05/16 03:03



//06-6-16
 
  接口分为查询状态类,更改状态类,分清楚点有利于规范代码。
  不要将不该暴露的数据写进头文件。
  凡是涉及到A对象的状态更新的,交给A来处理。
  尽量保持对象接口的简单,接口要精练。
  任务分配要具体,A只对象处理于A相关的事情,而且凡是与A对象相关的事情最好都交给A
  对象来处理,不要让细节蔓延,以至于最后不能维护,出现代码混乱,对象互相偶合。


//06-6-26
 
  如果一个对象需要从文件加载数据,不要写加载方法在这个类,继承一个新类,写在新类
  里。
  这样的好处是,你的基础类可以重复利用了!呵呵。与文件相关的东西被隔离出去了。
  〈07-2-13,结合工厂模式才最实际,见07-1-17。

//06-7-21

  如果一个类的数据太多,最好分别放到不同的结构里面,对他们进行整体的操作,
  比如有的数据需要存盘,有的是静态数据,有的是物理数据,有的是图形数据。

// 06-9-28

  关于书中的单实体模式的讨论,我有自己的看法。
  首先,好处明显,防止了多实体,而且是面向对象。
  问题是,如果他需要打开硬件,那么我们可以在返回实体的方法里面进行,这样避免了其
  他系统还没正常运行导致本系统开启失败。但是如果我们开启系统的时候需要一堆参数,
  怎么办?不能解决问题了。
  其次,单实体类的摧毁时机也需要控制,不能在主程序结束后进行,这就要求不能用
  static 来解决问题。
  这些问题有待讨论,所以使用单实体时头脑要清楚具体的需求,在进行设计。

// 06-11-10

1 命名空间

  关于命名空间的问题确实很头痛。接口的命名空间和接口实现的命名空间最好不要相同。否则只要一打开命名空间后,所有的类都暴露了出来,即便我们只使用接口。
 
  另外, 不要在头文件中打开一个命名空间,这样就丧失了命名空间的保护功能。
   
2 程序的不同状态的转换

  从一个状态切换到其他状态必须要求状态间保存彼此的引用。为了减少关联性,可以使用工厂模式。
 
// 06-11-13

1 奇怪的对象方法调用

  如果你有一个类A,他有一个静态方法 fun(), 一般的调用方法是
  A::fun (), 这是正规的调用。
 
  今天发现自己居然莫名其妙地写出了另一个形态:A().fun(),运行是好象没有问题。
  但是实际上他的工作方式是在栈上构造一个A,然后调用fun(), 超出生命期就摧毁A。
  所以,任何试图保存他的引用的行为都是危险的,呵呵,因为他只是个局部变量。
 
// 06-11-22

1 对于使用接口来设计的灵活性的认识

  接口趋向于强化一个标准,所有遵循标准的模块都可以拿来使用。
 
  在那些需要将来用更好的模块来更新的部分,这些部分不仅是数据组织方式,就数据的
  具体操作也不一样的地方, 但是他们完成相同的功能的时候,最好用接口。
 
  当然使用接口时必须遵循标准可能带来一些设计的小问题,但是这些问题都可以很好地解决,而且通过解决的途径看,接口似乎带来了更清晰的逻辑。
 
  但是要注意,设计借口的时候不要考虑的过于通用,否则,设计接口所花费的精力远大于接口所带来的好处,得不偿失。
 
2 关于静态数据与动态数据的分离
 
  在实际的程序中,一个碰撞模型里面装载的是相对静态的数据,这些数据从磁盘装载以后,很少更新,所以需要尽量地重用这些数据。
 
  比如上面的PRCollModel 里面的 array<PRCollFrame> 里面的数据就是相对静态的,这些数据允许类的多个实例共同享有,但是里面的mCurrFrame就是每个实例必须拥有的动态数据,必须分离出去。
 
  看例子:
 
  PRCollModel model;
  model.load ("...");
 
  class Man
  {
    void setCollModel (CollModel* model);
  };
 
  Man players[16];
 
  for (int i=0; i<16; i++)
    players[i].setCollModel (&model);
   
   
  这样就节省了大量的空间是不。
  如果原来的mCurrFrame依然在PRCollModel 里面的话, 下面的代码就会出问题:
 
  if (players[1].collide(&players[2])==true)
  {
    ....
  }
 
  在设计的时候要尽量多考虑哪些是动态数据,哪些是静态数据,这样可以优化结构。
  所以,可以这样改进:
 
  class ModelData
  {
    void load ();
    PRCollFrame *getFrame (int i);
  }
  
  class PRModel
  : CollModel
  {
    void update (int f, Vector *p, int dir)
    {
      mCurrFrame->copy(mData->getFrame(f));
     
      mCurrFrame->translate (p);
      mCurrFrame->rotate (dir);
    }
   
    CollFrame* getCurrFrame ()
    {
      return mCurrFrame;
    }
   
  private:
    PRCollFrame mCurrFrame;
    ModelData *mData;
  }
 
//06-11-23

1 静态数据与动态数据的分离(续)

  很多地方都需要这样的分离,特别是游戏对象方面。所以,有必要设计一个最好的结构
  来大范围地应用这个理论。
   
  先分析下,动态数据和静态数据肯定其中的一类要放入一个结构里面,至于这个结构是
  放在内部还是外部,要具体分析。如果放在内部的话,外部接口看起来会很简洁,内部
  数据封装的很好,但是实际上这样设计会有很多问题需要解决,比如怎样实例化它,怎
  样保证他具有扩展性之类。
   
  a, 静态数据放在外面
 
  class AnimData
  {
    array<Image*> Images;   
    bool load (FileStream *stream);
  }
 
  class Anim
  {
    void setStaticData (AnimData *d)   
  private:
    static AnimData* mStaticData;
    int    mCurrFrame;
  }
  然后我们想扩展他:
 
  class CollAnimData
  : AnimData
  {
    Sound * voice;   
    bool load (FileStream *f);
  }
  class CollAnim
  : Anim
  {
    void update ()   
    {
      CollAnimData *data = (CollAnimData*)mStaticData;
      if (...)
        data.voice->play ();       
    }
  }
   
2 关于 Animator类的一些说明
   
  本来以为这个类不仅可以分离静态数据,而且可以重用一些播放的算法类代码。
 
  这个类把具体的动画播放算法隔离出来,那么我们可以重用这些算法,而且可以动态切换动画的播放算法,实现不同的播放效果,这的确是对的,但是他并不能简单的分离静态的数据,所以,如果要达到好的重用效果的话,还要另外设计。

3 关于状态和菜单

  一个对象可以同时显示几个菜单,但是一个时刻内只有一个状态,所以,有必要引入状态和状态机的概念。