当前位置: 编程技术>软件工程/软件设计
本页文章导读:
▪Singleton 考虑内存的释放和多线程 GOF的《设计模式》中这样描述:保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能阻止你实例化多个对象。一个最好的.........
▪大话设计模式之装饰者模式 装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
利用组合(composition)和委托(delegation)可以在运行时具有继承行为的.........
▪input输入子系统源码部分函数分析 /*
* 源文件目录:
* /drivers/input/input.c
*/
入口函数:
static int __init input_init(void)
1、 err = class_register(&input_class); /* class设备节点生成 */
2、 err = input_proc_init(); /* 为添加到pro.........
[1]Singleton 考虑内存的释放和多线程
来源: 互联网 发布时间: 2013-11-19
GOF的《设计模式》中这样描述:保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能阻止你实例化多个对象。一个最好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。
也就是说,很多时候我们需要全局的对象,如一个工程中,数据库访问对象只有一个,这时,可以考虑使用单例模式。单例模式比全局对象好还包括:单例类可以继承,如下例。
单例模式的关键点在于:构造函数私有,静态的GetInstance。
另外,在C++中必须注意内存的释放。C++、Java、C#中还要注意多线程时的同步问题(下面的程序还没考虑多线程)。
#include <iostream>
using namespace std;
class Singleton {
private:
Singleton() {} //①constructor declare private
static Singleton* single; //③static member
public:
static Singleton* getInstance() { //② static member function
if(single == NULL)
single = new Singleton();
return single;
}
class Garbo { //它的唯一工作就是在析构函数中删除
public:
~Garbo() {
if(getInstance())
delete getInstance();
}
static Garbo garbo; //// 定义一个静态成员,在程序结束时,系统会调用
//它的析构函数,该析构函数会删除单例的唯一实例。
};
/*
* 考虑 memory leak 和 multithread(没有考虑)
*
*
* 使用这种方法释放C++单例模式对象有以下特征:
在单例类内部定义专有的嵌套类Garbo。
在单例类内定义私有的专门用于释放的静态成员。
利用程序在结束时析构全局变量的特性,选择最终的释放时机。
使用C++单例模式的代码不需要任何操作,不必关心对象的释放。*/
};
int main() {
Singleton *s1 = Singleton::getInstance();
Singleton *s2 = Singleton::getInstance();
if(s1 == s2)
cout << "Singleton is success";
}
作者:glx2012 发表于2013-4-8 10:45:55 原文链接
阅读:12 评论:0 查看评论
[2]大话设计模式之装饰者模式
来源: 互联网 发布时间: 2013-11-19
装饰者模式:动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
利用组合(composition)和委托(delegation)可以在运行时具有继承行为的效果。通过动态的组合对象,可以在新的代码添加新功能,而无须改动现有代码。既然没有改动现有代码,那么引进bug或产生意外的副作用的机会将大幅度减少。
利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能都利用组合的做法扩展对象的行为,既可以在运行时动态的进行扩展。
开闭原则:类应该对扩展开放,对修改关闭。代码应该如晚霞中的莲花一样的关闭(免于改变),如晨曦中的莲花一样的开放(能够扩展)。在遵循选择需要扩展的代码部分时要小心。每个地方都要采用开闭原则是一种浪费,也没有必要,通常会引入新的抽象层次,增加代码的复杂度,应该把注意力集中在设计中最有可能改变的地方。
//Beverage是一个抽象类,有两个方法getDescription()和cost()
public abstract class Beverage{
String description="Unknown Beverage";
//getDescription()已经在此实现了,但是cost必须在子类中实现。
public String getDescription() {
return description;
}
public abstract double cost();
}
/*首先,必须让CondimentDecorator能够取代Beverage,所以将CondimentDecorator扩展为Beverage类。
所有的调料装饰者都必须重新实现getDescription()方法 */
public abstract class CondimentDecorator extends Beverage{
public abstract String getDescription();
}
//写饮料的代码:
//首先,让Espresso(浓缩咖啡)扩展自Beverage类,因为是一种Espresso饮料。
public class Espresso extends Beverage{
public Espresso(){
//为了要设置饮料的描述,我们写了一个构造器。
description="Espresso";
}
public double cost(){
return 1.99;
}
}
//写调料代码
//Mocha是一个装饰者,扩展自CondimentDecorator,CondimentDecorator扩展自Beverage
public class Mocha extends CondimentDecorator{
Beverage beverage;
/*要让Mocha能够引用一个Beverage,做法如下:
1、用一个实例变量记录饮料,也就是被装饰者。
2、想办法让被装饰着(饮料)被记录到实例变量中。如把饮料当做构造器的参数,再由构造器将此饮料记录在实例变量中。*/
public Mocha(Beverage beverage){
this.beverage=beverage;
}
//我们希望不只是描述饮料,而是完成的连调料也描述出来。所以,首先利用委托的办法,得到一个叙述,然后在其后面加上附加的叙述。
public String getDescription(){
return beverage.getDecription()+",Mocha";
}
//要计算带Mocha的饮料的价钱,首先把调用委托类给被装饰对象,以计算价钱,然后再加上Mocha的价钱,得到最后结果。
public double cost(){
return .20+beveragr.cost();
}
}
//供应咖啡
public class StarbuzzCoffee{
public static void main(String args[]){
//定一杯Espresso,不需要调料,打印出它的描述与价钱。
Beverage beverage=new Espresso();
System.out.printIn(beverage.getDescription()+" $"+beverage.cost());
//制造出一个DarkRoast对象,用Mocha装饰它,用第二个Mocha装饰它,用Whip装饰它。
Beverage beverage2=new DarkRoast();
beverage2=new Mocha(beverage2);
beverage2=new Mocha(beverage2);
beverage2=new Whip(beverage2);
System.out.printIn(beverage2.getDescription()+" $"+beverage2.cost());
//最后再来一杯调料味豆浆,摩卡,奶泡的HouseBlend咖啡。
Beverage beverage3=new HouseBlend();
beverage3=new Mocha(beverage3);
beverage3=new Mocha(beverage3);
beverage3=new Whip(beverage3);
System.out.printIn(beverage3.getDescription()+" $"+beverage3.cost());
}
}
作者:lantingxv_jing 发表于2013-4-8 21:29:05 原文链接
阅读:50 评论:1 查看评论
[3]input输入子系统源码部分函数分析
来源: 互联网 发布时间: 2013-11-19
/*
* 源文件目录:
* /drivers/input/input.c
*/
入口函数:
static int __init input_init(void)
1、 err = class_register(&input_class); /* class设备节点生成 */
2、 err = input_proc_init(); /* 为添加到proc文件系统的设备节点文件做一些初始化工作 */
3、 err = register_chrdev(INPUT_MAJOR, "input", &input_fops); /* 注册为字符型驱动 */
/*
* input_fops结构体分析
*/
static const struct file_operations input_fops = {
.owner = THIS_MODULE, /* 模块所属者 */
.open = input_open_file, /* 打开操作函数 */
.llseek = noop_llseek, /* 绕过llseek操作 */
};
/*
* input_open_file函数分析
*/
static int input_open_file(struct inode *inode, struct file *file)
1. struct input_handler *handler; /* handler声明 */
/*
* input_hanler结构体:
* struct input_handler {
void *private;
void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value);
bool (*match)(struct input_handler *handler, struct input_dev *dev);
int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id);
void (*disconnect)(struct input_handle *handle);
void (*start)(struct input_handle *handle);
const struct file_operations *fops;
int minor;
const char *name;
const struct input_device_id *id_table;
* struct list_head h_list;
* struct list_head node;
* };
*/
2. const struct file_operations *old_fops, *new_fops = NULL; /* file_operations结构体声明 */
3. err = mutex_lock_interruptible(&input_mutex); /* 上互斥锁操作 */
4. handler = input_table[iminor(inode) >> 5]; /* input_table链表中第iminor(inode) >> 5节点的handler */
5. if (handler) /* 是否存在此handler */
new_fops = fops_get(handler->fops); /* 存在内容则取出此handler的fops结构体赋予new_fops */
6. mutex_unlock(&input_mutex); /* 解除互斥锁 */
7. old_fops = file->f_op;
file->f_op = new_fops; /* 交换file_operation,使input设备可使用相应的操作函数 */
8. err = new_fops->open(inode, file); /* 使用对于的打开函数 */
9. fops_put(old_fops); /* 释放old_fops */
/*
* input_register_device函数分析
*/
int input_register_device(struct input_dev *dev);
1. static atomic_t input_no = ATOMIC_INIT(0); /* 原子变量初始化 */
2. struct input_handler *handler; /* 新handler声明 */
3. /* Every input device generates EV_SYN/SYN_REPORT events. */ /* 设置dev结构体 */
__set_bit(EV_SYN, dev->evbit);
/* KEY_RESERVED is not supposed to be transmitted to userspace. */
__clear_bit(KEY_RESERVED, dev->keybit);
/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
input_cleanse_bitmasks(dev);
4. init_timer(&dev->timer); /* 初始化一个定时器 */
5. error = device_add(&dev->dev); /* 添加设备 */
/*
* device_add函数分析
*/
int device_add(struct device *dev)
1. dev = get_device(dev); /* 获取dev的kobj */
struct device *get_device(struct device *dev);
\--->return dev ? to_dev(kobject_get(&dev->kobj)) : NULL;
2. parent = get_device(dev->parent); /* 获取父类驱动的kobj */
setup_parent(dev, parent); /* 启动父类驱动 */
3. error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);/* 将dev->kobj, dev->kobj.parent添加至内核中 */
6. error = mutex_lock_interruptible(&input_mutex); /* 上互斥锁 */
7. list_add_tail(&dev->node, &input_dev_list); /* 添加到input_dev_list队列中 */
8. list_for_each_entry(handler, &input_handler_list, node)
input_attach_handler(dev, handler); /* 遍历每个节点 */
9. input_wakeup_procfs_readers(); /* 唤醒procfs_readers */
10. mutex_unlock(&input_mutex); /* 解除互斥锁 */
/*
* input_register_handler函数分析
*/
int input_register_handler(struct input_handler *handler);
1. struct input_dev *dev; /* input_dev结构体指针声明 */
2. retval = mutex_lock_interruptible(&input_mutex); /* 上互斥锁 */
3. INIT_LIST_HEAD(&handler->h_list); /* 初始化list的前级与后继指针都指向list */
4. if (handler->fops != NULL) { /* 判断是否有值handler->fops */
if (input_table[handler->minor >> 5]) { /* 判断input_table[handler->minor >> 5]节点是否有值 */
retval = -EBUSY;
goto out;
}
input_table[handler->minor >> 5] = handler; /* 将handler添加到input_table[handler->minor >> 5]节点上 */
}
5. list_add_tail(&handler->node, &input_handler_list); /* 将handler->node放入到队列中 */
6. list_for_each_entry(dev, &input_dev_list, node)
input_attach_handler(dev, handler); /* 遍历每个节点 */
7. input_wakeup_procfs_readers(); /* 唤醒procfs_readers */
/*
* input_allocate_device函数分析
*/
struct input_dev *input_allocate_device(void);
1. struct input_dev *dev; /* input_dev结构体声明 */
2. dev = kzalloc(sizeof(struct input_dev), GFP_KERNEL); /* input_dev结构体空间分配 */
/*
* 分析kzalloc函数
*/
static inline void *kzalloc(size_t size, gfp_t flags)
\-->return kmalloc(size, flags | __GFP_ZERO);
3. if (dev) { /* 初始化dev的成员变量 */
dev->dev.type = &input_dev_type;
dev->dev.class = &input_class;
device_initialize(&dev->dev);
/*
* device_initialize函数
*/
void device_initialize(struct device *dev)
{
dev->kobj.kset = devices_kset;
kobject_init(&dev->kobj, &device_ktype);
INIT_LIST_HEAD(&dev->dma_pools);
mutex_init(&dev->mutex);
lockdep_set_novalidate_class(&dev->mutex);
spin_lock_init(&dev->devres_lock);
INIT_LIST_HEAD(&dev->devres_head);
device_pm_init(dev);
set_dev_node(dev, -1);
}
/*
* 互斥锁初始化
*/
mutex_init(&dev->mutex);
/*
* 自旋锁初始化
*/
spin_lock_init(&dev->event_lock);
INIT_LIST_HEAD(&dev->h_list);
INIT_LIST_HEAD(&dev->node);
__module_get(THIS_MODULE);
}
/*
* input_attach_handler函数分析
*/
static int input_attach_handler(struct input_dev *dev, struct input_handler *handler);
1. id = input_match_device(handler, dev); /* 比较handler与dev的id */
2. error = handler->connect(handler, dev, id); /* 调用相应handler的connet函数 */
/*
* input_register_handle函数分析
*/
int input_register_handle(struct input_handle *handle)
1. error = mutex_lock_interruptible(&dev->mutex); /* 上互斥锁 */
2. if (handler->filter) /* 使dev->h_list指向handle->d_node */
list_add_rcu(&handle->d_node, &dev->h_list);
else
list_add_tail_rcu(&handle->d_node, &dev->h_list);
3. mutex_unlock(&dev->mutex); /* 解除互斥锁 */1
4. list_add_tail_rcu(&handle->h_node, &handler->h_list); /* 使handler->h_list指向handle->h_node */
作者:toraloo 发表于2013-4-9 15:28:36 原文链接
阅读:38 评论:0 查看评论
最新技术文章: