2013年(8)
分类: C/C++
2013-02-03 23:17:11
Factory 模式
主要为了提高内聚(Cohesion)和松耦合(Coupling)性,同时为了防止一些蹩脚实现提供的设计模式。
原理: 网上太多了。
使用原因 (转载) :
在面向对象系统设计中经常可以遇到以下的两类问题:
1)为了提高内聚(Cohesi on)和松耦合(Coupling),我们经常会抽象出一些类的公共
接口以形成抽象基类或者接口。这样我们可以通过声明一个指向基类的指针来指向实际的子
类实现,达到了多态的目的。这里很容易出现的一个问题n 多的子类继承自抽象基类,我们不得不在每次要用到子类的地方就编写诸如ne w ×××; 的代码。这里带来两个问题 1 )客户程序员必须知道实际子类的名称(当系统复杂后,命名将是一个很不好处理的问题,为了处理可能的名字冲突,有的命名可能并不是具有很好的可读性和可记忆性,就姑且不论不同程序员千奇百怪的个人偏好了。),
2)程序的扩展性和维护变得越来越困难
2)还有一种情况就是在父类中并不知道具体要实例化哪一个具体的子类。这里的意思
为:假设我们在类A 中要使用到类B ,B 是一个抽象父类,在A 中并不知道具体要实例化那一个B 的子类,但是在类A 的子类D 中是可以知道的。在A 中我们没有办法直接使用类似于new ×××的语句,因为根本就不知道×××是什么。
以上两个问题也就引出了Factory模式的两个最重要的功能:
1)定义创建对象的接口,封装了对象的创建;
2)使得具体化类的工作延迟到了子类中。
上面文字转载
网上c++ 代码 有点抽象, 有时候看不出他的好处,这里直接写一个真实实例的源码:
linux 应用层加锁其中有两种方式pthread_spinlcok_t pthread_mutex_t;
头文件 lock.h
#ifndef __LOCK_H__
#define __LOCK_H__
typedef void* lock_t;
typedef enum
{
LOCK_PTSPIN,
LOCK_PTMUTEX,
LOCK_BUTTON
}lock_type;
typedef struct lock_ops {
lock_t (*alloc)(void);
int (*acquire)(lock_t l);
int (*release)(lock_t l);
void (*free)(lock_t l);
} lock_ops;
lock_ops *lock_ops_create(lock_type locktype);
void lock_free(lock_t l);
int lock_acquire(lock_t l);
int lock_release(lock_t l);
lock_t lock_alloc(void);
#endif /* __LOCK_H__ */
Lock.c
#include "lcok.h"
extern lock_ops spin_ops;
extern lock_ops ptspin_ops;
#ifdef LOCK_PTTHREAD_MUTEX
#define OPS spin_ops
#elif defined(LOCK_PTTHREAD_PSIN)
#define OPS ptmutex_ops
#else
#error No lock type defined
#endif
lock_t lock_alloc (void)
{
lock_t mr;
mr = OPS.alloc();
return mr;
}
int lock_acquire (lock_t lock)
{
if (NULL == lock)
{
return -1;
}
return OPS.acquire(lock);
}
int lock_release (lock_t lock)
{
if (NULL == lock)
{
return -1;
}
return OPS.release(lock);
}
void lock_free (lock_t lock)
{
if (NULL == lock)
{
return;
}
OPS.free(lock);
}
lock_ops *lock_ops_create(lock_type locktype)
{
switch(locktype)
{
case LOCK_PTSPIN:
return &spin_ops;
case LOCK_PTMUTEX
return ptmutex_ops;
default:
return NULL;
}
return NULL;
}
Pthread_mutex_lock.c
#include
#include "lock.h"
static lock_t ptmutex_alloc(void)
{
pthread_mutex_t *m;
int err;
m = malloc(sizeof(pthread_mutex_t));
if (NULL == m)
{
return NULL;
}
err = pthread_mutex_init(m, NULL);
if (err < 0)
{
free(m);
m = NULL;
}
return m;
}
static int ptmutex_acquire(lock_t l)
{
int err;
err = pthread_mutex_lock(l);
if (err < 0);
{
return -1;
}
return 0;
}
static int ptmutex_release(lock_t l)
{
int err;
err = pthread_mutex_unlock(l);
if (err < 0);
{
return -1;
}
return 0;
}
static void ptmutex_free(lock_t l)
{
pthread_mutex_destroy(l);
free(l);
}
lock_ops ptmutex_ops = {
.alloc = ptmutex_alloc,
.acquire = ptmutex_acquire,
.release = ptmutex_release,
.free = ptmutex_free,
};
Pthread_spinlock.c
#include
#include "lock.h"
static lock_t ptspin_alloc(void)
{
pthread_spinlock_t *m;
int err;
m = malloc(sizeof(pthread_spinlock_t ));
if (NULL == m)
{
return NULL;
}
err = pthread_spin_init(m, 0);
if (err < 0)
{
free(m);
m = NULL;
}
return m;
}
static int ptspin_acquire(lock_t l)
{
int err;
err = pthread_spin_lock(l);
if (err < 0);
{
return -1;
}
return 0;
}
static int ptspin_release(lock_t l)
{
int err;
err = pthread_spin_unlock(l);
if (err < 0);
{
return -1;
}
return 0;
}
static void ptspin_free(lock_t l)
{
pthread_spin_destroy(l);
free(l);
}
lock_ops ptspin_ops = {
.alloc = ptspin_alloc,
.acquire = ptspin_acquire,
.release = ptspin_release,
.free = ptspin_free,
};
#include
#include
#include "lock."
Int main(int argc, char *argv[])
{
lock_ops *lock_factory = lock_ops_create(LOCK_PTSPIN); /* 创建工厂*/
lock_t lock;
If (NULL == lock_factory )
{
Return -1;
}
Lock = lock_factory->alloc(); /* 创建锁 */
}
应用场景: 给出的例子就是很好的实例。
对外的接口只需要关注头文件。
使用工厂模式有几个特点:
1、对外只暴露 函数接口,接口作为实现的抽象
2、整个接口可能有多个实现方式。
这种模块其实也很常见,
比如,
1、要测试某种锁的性能,只需要改动lock_ops_create(LOCK_PTSPIN); 即可
讨论:
1、 直接将某个或者多个函数定义成一个宏,也能实现这种抽象。 缺点:不好维护,每次变动需要改动所有的宏
2、 直接使用宏控制 #ifdef等,直接实现多个具体实现,而且还可以再makefile中控制。
优点: 保持常用的c语言编程的调用的习惯, 可以再makefile中控制。
缺点: 不好维护,代码中可能到处都是#ifdef,如果这个实现方式多的话,这将是维护的灾难