不从层次的抽象
“….用继承表现不同层次的抽象….”, 原句是怎么说的我已经记不清了, 但每当我在编程时遇到困难, 想想这句话, 总能给我很多启发.
这句话的深意很难用简单的语言表达, 但是最近我看到一个”灯和开关”的例子, 正好可以用来描述这句话的一部分思想.
这个图我没有画全, 下面是代码:
class Lamp { public: Lamp() : m_bShining(false){} virtual ~Lamp(); public: bool IsShining(); // 是否亮 bool IsFailure(); // 是否故障 public: virtual Switcher& GetSwitcher() = 0; protected: void SetShining(bool bShining); private: bool m_bShining; }; class Switcher { public: enum State{ ON, OFF}; public: Switcher(void); virtual ~Switcher(void); public: Switcher::State GetState() { return m_state; } public: virtual void TurnOn() { m_state = ON; } virtual void TurnOff() { m_state = OFF; } private: State m_state; };
Switcher 和 Lamp位于第一个抽象层, 大部分的程序员将在这一层工作, 以这一层为基础构建其他代码. 编写和维护这一层的程序员将工作在第一层和第二层:
class Torch : public Lamp { public: Torch(void); virtual ~Torch(void); public: void LigthUp(); public: virtual Switcher& GetSwitcher(); private: Flint m_flint; }; class FlashLamp : public Lamp { public: FlashLamp(void); virtual ~FlashLamp(void); public: virtual Switcher& GetSwitcher(); public: void Open(); void LightUp(); void Close(); private: bool m_bOpened; Shutter m_shutter; }; // -------------------------------------------------------------------------------------------- class Torch; class Flint : public Switcher { public: Flint(Torch* pTorch); virtual ~Flint(void); public: virtual void TurnOn(); virtual void TurnOff(); private: Torch* m_pTorch; }; void Flint::TurnOn() { if (m_pTorch) { for ( int i = 0; i < 5; ++i) m_pTorch->LigthUp(); // Torch有一定几率点不着 } Switcher::TurnOn(); } void Flint::TurnOff() { // do something Switcher::TurnOff(); } class FlashLamp; class Shutter : public Switcher { public: Shutter(FlashLamp* pFlashLamp); virtual ~Shutter(void); public: virtual void TurnOn(); virtual void TurnOff(); private: FlashLamp* m_pFlashLamp; }; void Shutter::TurnOn() { if (m_pFlashLamp) { m_pFlashLamp->Open(); m_pFlashLamp->LightUp(); } Switcher::TurnOn(); } void Shutter::TurnOff() { if (m_pFlashLamp) { m_pFlashLamp->Close(); } Switcher::TurnOff(); }
第一层比第二层更加抽象, 第二层比第一层更加具体. 我们可以在Shutter和Flint这两个Switcher中编写和FlashLamp, Torch紧密关联的代码, 而不会对第一层造成影响, 因为高级抽象层是不会受到低级抽象层的影响的, 但是反过来说, 低级抽象层却必须要遵从高级抽象层定义的规则.
我认为, 低耦合是指在高级抽象层上进行低耦合, 而在低级抽象层上施行耦合紧密的设计是不会影响到程序的低耦合性质的. 在这个程序中Lamp和Switcher仅工作在自己的抽象层, 并不对下层代码做任何假设, 这是一个比较标准的做法.
如果在实际工作中碰到不同抽象层代码叠交的现象, 则说明高级抽象层没有设计好, 或者定义的功能不够抽象. 不过, 谁又在乎抽不抽象呢? :)
关键字 不从层次的抽象
推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架