Fctory Method模式

本文探讨了如何使用工厂方法模式来避免运行时类型查询的问题。通过将类型映射逻辑封装在各个具体子类中,实现了更灵活的设计。这种方法不仅减少了代码间的耦合度,还简化了维护工作。

 一个高级设计通常要求基于一个现有对象类型来创建一个“适当”类型的对象。例如,我们困难拥有一个指向某种类型的Employee对象的指针或引用,现在需要为该类型的Employee生成一个适当类型的HRInfo对象,

 

     Employee

 

  HRInfo

 

Salary

Hourly

Temp

 

StdInfo

Tempinfo

          

   |……………………|………………………………………>|              |

|…………………………………………>|

这里,我们拥有两个几乎平行的Employee和HRInfo层次结构。Salary和Hourly类型的雇员需要产生StdInfo对象,而Temp雇员则需要产生TempInfo对象。应该如何将一个雇员与其对应的人力资源信息映射?

高级设计方案非常简单:“为这个雇员创建一个适当类型的记录“。不幸的是,程序员通常将此类需求当成执行运行期类型查询的借口。换句话说,为了决定待产生的HRInfo对象的类型,实现此项需求的代码仅仅是询问一系列关于Employee的确切类型问题。

一个常见,但总是错误的方式是使用“类型编码”和switch语句:

 class Employee {

  public:

    enum Type { SALARY , HOURLY , TEMP };

    Type type() const { return type_ ;}

    //…

  private:

    Type type_;

    //……

};

//…

HRInfo *getInfo (const Employee &e){

 Switch ( e.type () )

 {

  case SALARY:

  case HOURLY: return new StdInfo ( e );

case TEMP : return new TempInfo ( static_cast<const TEMP>(e));

  default :return 0; //未知的类型编码

}

}

 另外一种几乎同样糟糕的方式,是使用dynamic_cast来询问关于Employee对象一系列的私人问题:

HRInfo *getInfo ( const Employee &e ) {

  If( const Salary *s = dynamic_cast<const Salary *>(&e))

      Return new StdInfo ( s );

  Else if ( const Hourly *h = dynamic_cast<const Hourly *>(&e))

      Return new Stdinfo ( h );

  Else if ( const Temp *t = dynamic_cast<const Temp *>(&e))

      Return new Stdinfo ( t );

Else

        Return 0;//未知的employee类型

}

  这两种getInfo实现的主要缺点在于,他们与所有从Employee和HRInfo类派生下来的具体类型相耦合,并且它们还必须熟悉从每一种Employee类型到其相应的HRInfo类型的映射。任一Employee,HRInfo或二者之间的映射发生了改动,都需要我们去维护代码。在不同的开发组困难不断向这两个继承层次结构中添加新类型或从中移除类型的情况下,这种维护工作几乎总是不能正确地执行,另一个问题是,这两种方式都可能无法识别Employee实参的确切类型,从而要求调用getInfo的代码提供对错误情况的处理。

  根据上面的分析,正确的方式是去考虑从每一种Employee类型到对应的HRInfo类型的映射应该置于何处。换句话说,岁最清楚一个Temp Employee需要何种HRInfo对象?理所当然,是Temp Employee自己:

class Temp : public Employee {

 public :

  //…

  TempInfo *getInfo () const

  { return new TemoInfo (*this);}

  //…

};

  还有一个问题,我们可能不知道我们是在处理一个Temp Employee而不是别的类型的Employee,这个问题很好解决,只要提供一个(纯)虚函数就可以了:

class Employee {

 public:

  //…

  virtual HRInfo *getInfo () const = 0;//Factory method

//…

};

 

 这是一个Factory Method模式的实例。实际上,我们不是向employee询问一系列的私人问题。而是说“不管你是什么类型的employee,请为自己生成适当的HRInfo对象”:

Employee * e =getAnExamplee ( );

//…

HRInfo *info = e->getInfo () ; //使用Factory Method

 

Factory Method的本质在于,基类提供一个虚函数“挂钩”,用于产生适当的“产品”。每个派生类可以重写继承的虚函数,为自己产生适当的产品。实际上,我们具备了使用一个未知类型的对象来产生另一个未知类型的对象的能力。

使用Factory Method模式通常意味着一个高级设计需要基于一个对象的确切类型产生另一个“适当”的对象,这样的需要往往发生于存在多个平行或几乎平行的类层次结构的情况下。Factory Method模式通常是解决一系列运行期类型查询问题的好方法。

 
// Define constants for LED on/off states, repeat flag, event and state types #define LED_ON (0x1) #define LED_OFF (0x0) #define LED_REPEAT (0x1) #define LED_EVENT_TYPE (0x0) #define LED_STATE_TYPE (0x1) // Define constants for various LED patterns typedef enum { LED_EVENT_POWER_ON, LED_EVENT_POWER_OFF, LED_EVENT_FACTORY_RESET, LED_EVENT_CONNECTED,//3 LED_EVENT_LINEIN_PLUGININ, LED_STATE_PAIRING, LED_STATE_RECONNECT, LED_STATE_CONNECTABLE,//7 LED_STATE_CONNECTED, LED_STATE_POWER_OFF, LED_STATE_NO_CONNECTION, LED_STATE_BATTERY_LOW, //11 LED_STATE_BATTERY_CHARGING, LED_STATE_BATTERY_FULL, LED_STATE_FACTORY_BLUR, LED_STATE_LINEIN, LED_LAST_INDEX } LedPattern_t; #define LED_NUM_PATTERNS ( LED_LAST_INDEX ) // Define the LED entry structure, including LED mask, time parameters for lighting up and off, and blink count typedef struct { uint8_t led_mask; // LED mask, used to identify the specific LED channel uint16_t rise_time; // Duration from off to the brightest state (milliseconds) uint16_t brightest_time; // Duration of the brightest state (milliseconds) uint16_t fall_time; // Duration from the brightest to off state (milliseconds) uint16_t darkest_time; // Duration of the off state (milliseconds) uint16_t blink_count; // Number of blinks uint16_t total_time; } LedEntry; // Define the LED header structure, including LED pattern, state or event type, and timeout typedef struct { uint8_t num_entries; LedPattern_t pattern; // LED pattern uint8_t state_or_event; // State or event type uint8_t on_or_off; uint16_t timeout; // Timeout in milliseconds } LedHeader; // Define the LED structure, including header information and a pointer to the LED entry typedef struct { LedHeader header; // LED header information const LedEntry* entries; // Pointer to the LED entry } LedDisplayConfig; extern const LedDisplayConfig gLedDisplayConfigs[];#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) // Define LED channel masks #define BLUE_LED_MASK (HAL_ISINK_CHANNEL_1) #define RED_LED_MASK (HAL_ISINK_CHANNEL_0) // Blue LED power-on event pattern static const LedEntry blue_led_power_on_pattern_event[] = { // Blue flashes quickly twice {BLUE_LED_MASK, 0, 250, 0, 250, 2, 0} }; // Blue LED power-off event pattern static const LedEntry blue_led_power_off_pattern_event[] = { // Blue flashes quickly twice {BLUE_LED_MASK, 0, 250, 0, 250, 2, 0} }; // Blue LED factory reset event pattern static const LedEntry blue_led_factory_reset_pattern_event[] = { // Blue flashes quickly twice {BLUE_LED_MASK, 0, 250, 0, 250, 2, 0} }; // Blue LED connected event pattern static const LedEntry blue_led_connected_pattern_event[] = { // Blue stays on for 5 seconds then turns off {BLUE_LED_MASK, 0, 5000, 0, 0, 1, 0} }; // Blue LED pairing state pattern static const LedEntry blue_led_pairing_pattern_state[] = { // Blue flashes quickly {BLUE_LED_MASK, 250, 150, 250, 150, 0, 0} }; // Blue LED reconnected state pattern static const LedEntry blue_led_reconnect_pattern_state[] = { // Blue flashes slowly {BLUE_LED_MASK, 1000, 500, 1000, 500, 0, 0} }; // Blue LED connectable state pattern static const LedEntry blue_led_connectable_pattern_state[] = { // Blue flashes slowly {BLUE_LED_MASK, 1000, 500, 1000, 500, 0, 0} }; // Blue LED connected state pattern static const LedEntry blue_led_connected_pattern_state[] = { // Blue is off {BLUE_LED_MASK, 0, 0, 0, 0, 0, 0} }; // Blue LED power off state pattern static const LedEntry blue_led_power_off_pattern_state[] = { // Blue is off {BLUE_LED_MASK, 0, 0, 0, 0, 0, 0} }; // Blue LED bt no connection state pattern static const LedEntry blue_led_no_connection_pattern_state[] = { // Blue flashes slowly {BLUE_LED_MASK, 1000, 500, 1000, 500, 0, 0} }; // Red LED low battery state pattern static const LedEntry red_led_battery_low_pattern_state[] = { // Red flashes slowly {RED_LED_MASK, 0, 500, 0, 2000, 0, 0} }; // Red LED battery charging state pattern static const LedEntry red_led_battery_charging_pattern_state[] = { // Red stays on constantly {RED_LED_MASK, 0, 500, 0, 0, 0, 0} }; // Red LED battery full state pattern static const LedEntry red_led_battery_full_pattern_state[] = { // Red is off {RED_LED_MASK, 0, 0, 0, 0, 0, 0} }; // Blue LED fctory test event pattern static const LedEntry blue_led_factory_test_pattern_event[] = { // Blue stays on constant {BLUE_LED_MASK, 0, 5000, 0, 0, 0, 0} }; // Blue LED linein test event pattern static const LedEntry blue_led_linein_pattern_state[] = { // Blue stays on constant {BLUE_LED_MASK, 0, 0, 0, 0, 0, 0} }; static const LedEntry blue_led_linein_plugin_pattern_event[] = { // Blue stays on constant {BLUE_LED_MASK, 0, 200, 0, 200, 3, 1000}, {BLUE_LED_MASK, 0, 0, 0, 1000, 0, 1000}, {BLUE_LED_MASK, 0, 200, 0, 200, 3, 0}, }; // Define an array of LED patterns, including information for all LED patterns const LedDisplayConfig gLedDisplayConfigs[LED_NUM_PATTERNS] = { { {ARRAY_SIZE(blue_led_power_on_pattern_event), LED_EVENT_POWER_ON, LED_EVENT_TYPE, LED_ON, 1200}, blue_led_power_on_pattern_event }, { {ARRAY_SIZE(blue_led_power_off_pattern_event), LED_EVENT_POWER_OFF, LED_EVENT_TYPE, LED_ON, 1200}, blue_led_power_off_pattern_event }, { {ARRAY_SIZE(blue_led_factory_reset_pattern_event), LED_EVENT_FACTORY_RESET, LED_EVENT_TYPE, LED_ON, 1200}, blue_led_factory_reset_pattern_event }, { {ARRAY_SIZE(blue_led_connected_pattern_event), LED_EVENT_CONNECTED, LED_EVENT_TYPE, LED_ON, 5000}, blue_led_connected_pattern_event }, { {ARRAY_SIZE(blue_led_linein_plugin_pattern_event), LED_EVENT_LINEIN_PLUGININ, LED_EVENT_TYPE, LED_ON, 3000}, blue_led_linein_plugin_pattern_event }, { {ARRAY_SIZE(blue_led_pairing_pattern_state), LED_STATE_PAIRING, LED_STATE_TYPE, LED_ON, 0 }, blue_led_pairing_pattern_state }, { {ARRAY_SIZE(blue_led_reconnect_pattern_state), LED_STATE_RECONNECT, LED_STATE_TYPE, LED_ON, 0 }, blue_led_reconnect_pattern_state }, { {ARRAY_SIZE(blue_led_connectable_pattern_state), LED_STATE_CONNECTABLE, LED_STATE_TYPE, LED_ON, 0 }, blue_led_connectable_pattern_state }, { {ARRAY_SIZE(blue_led_connected_pattern_state), LED_STATE_CONNECTED, LED_STATE_TYPE, LED_OFF, 0 }, blue_led_connected_pattern_state }, { {ARRAY_SIZE(blue_led_power_off_pattern_state), LED_STATE_POWER_OFF, LED_STATE_TYPE, LED_OFF, 0 }, blue_led_power_off_pattern_state }, { {ARRAY_SIZE(blue_led_no_connection_pattern_state), LED_STATE_NO_CONNECTION, LED_STATE_TYPE, LED_ON, 0 }, blue_led_no_connection_pattern_state }, { {ARRAY_SIZE(red_led_battery_low_pattern_state), LED_STATE_BATTERY_LOW, LED_STATE_TYPE, LED_ON, 0 }, red_led_battery_low_pattern_state }, { {ARRAY_SIZE(red_led_battery_charging_pattern_state), LED_STATE_BATTERY_CHARGING,LED_STATE_TYPE, LED_ON, 0 }, red_led_battery_charging_pattern_state }, { {ARRAY_SIZE(red_led_battery_full_pattern_state), LED_STATE_BATTERY_FULL, LED_STATE_TYPE, LED_OFF, 0 }, red_led_battery_full_pattern_state }, { {ARRAY_SIZE(blue_led_factory_test_pattern_event), LED_STATE_FACTORY_BLUR, LED_STATE_TYPE, LED_ON, 0 }, blue_led_factory_test_pattern_event }, { {ARRAY_SIZE(blue_led_linein_pattern_state), LED_STATE_LINEIN, LED_STATE_TYPE, LED_OFF, 0 }, blue_led_linein_pattern_state } }; void app_cchip_leds_show_event(uint8_t led_index); void app_cchip_leds_show_state(uint8_t led_index);根据上面灯效数据,用C语音和和freertos操作系统实现这两个函数
08-19
根据原作 https://pan.quark.cn/s/459657bcfd45 的源码改编 Classic-ML-Methods-Algo 引言 建立这个项目,是为了梳理和总结传统机器学习(Machine Learning)方法(methods)或者算法(algo),和各位同仁相互学习交流. 现在的深度学习本质上来自于传统的神经网络模型,很大程度上是传统机器学习的延续,同时也在不少时候需要结合传统方法来实现. 任何机器学习方法基本的流程结构都是通用的;使用的评价方法也基本通用;使用的一些数学知识也是通用的. 本文在梳理传统机器学习方法算法的同时也会顺便补充这些流程,数学上的知识以供参考. 机器学习 机器学习是人工智能(Artificial Intelligence)的一个分支,也是实现人工智能最重要的手段.区别于传统的基于规则(rule-based)的算法,机器学习可以从数据中获取知识,从而实现规定的任务[Ian Goodfellow and Yoshua Bengio and Aaron Courville的Deep Learning].这些知识可以分为四种: 总结(summarization) 预测(prediction) 估计(estimation) 假想验证(hypothesis testing) 机器学习主要关心的是预测[Varian在Big Data : New Tricks for Econometrics],预测的可以是连续性的输出变量,分类,聚类或者物品之间的有趣关联. 机器学习分类 根据数据配置(setting,是否有标签,可以是连续的也可以是离散的)和任务目标,我们可以将机器学习方法分为四种: 无监督(unsupervised) 训练数据没有给定...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值