当前位置: 编程技术>软件工程/软件设计
本页文章导读:
▪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 查看评论
最新技术文章: