单例模式:单例模式的作用就是解决“应用中只有一个实例”的一类问题
//一个简单的例子
.h文件
@interface SDKImpl : NSObject
{
}
+(SDKImpl *) instance;
@end
.m文件
static SDKImpl *instance; //静态类对象,作用于局
@implementation SDKImpl
+(SDKImpl *)instance; //静态类方法+
{
if(!instance)
instance = [[SDKImpl alloc] init]; //如果这个对象不存在,初始化他 instance = [[SDKImpl alloc] init]; return instance;返回instance
return instance;
}
@end
差异:
委托模式:师傅(通用框架)----协议(sleep,eat,work)----徒弟(实现协议)
委托是为了降低一个对象的复杂度和耦合度,使其能够更具通用性而将其中一些处理置于委托对象中的编码方式。。
—————————————————————
观察者模式:一个对象状态的改变也会连带影响其他很多对象的状态,如:(这边的例子百度下就有SDK接入的时候也用到,回头看看houmee实习日记4.9)或者百度一下都有很多。
抽象主题(增删观察者) -------------》抽象观察者(跟新接口)
具体主题 -------X弱引用X------》具体观察者
(发生改变时) ------》 (给所有登记过的观察者发出ms)
具体主题实现抽象主题,具体观察者实现抽象观察者,具体主题状态发生改变,会通知登记过的观察者.
在软件系统中,一个对象状态的改变也会连带影响其他很多对象的状态发生改变。能够实现这一需求的设计方案有很多,但能够做到复用性强且对象之间匿名通信的,观察者模式是其中最为适合的一个。
参考:http://segmentfault.com/q/1010000000130046 观察者模式与委托模式的区别
参考:http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html 观察者模式
回调函数的使用:
什么是回调函数?
简而言之,回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。
为什么要使用回调函数?
因为可以把调用者与被调用者分开。调用者不关心谁是被调用者,所有它需知道的,只是存在一个具有某种特定原型、某些限制条件(如返回值为int)的被调用函数。
如果想知道回调函数在实际中有什么作用,先假设有这样一种情况,我们要编写一个库,它提供了某些排序算法的实现,如冒泡排序、快速排序、shell排序、shake排序等等,但为使库更加通用,不想在函数中嵌入排序逻辑,而让使用者来实现相应的逻辑;或者,想让库可用于多种数据类型(int、float、string),此时,该怎么办呢?可以使用函数指针,并进行回调。
回调可用于通知机制,例如,有时要在程序中设置一个计时器,每到一定时间,程序会得到相应的通知,但通知机制的实现者对我们的程序一无所知。而此时,就需有一个特定原型的函数指针,用这个指针来进行回调,来通知我们的程序事件已经发生。实际上,SetTimer() API使用了一个回调函数来通知计时器,而且,万一没有提供回调函数,它还会把一个消息发往程序的消息队列。
另一个使用回调机制的API函数是EnumWindow(),它枚举屏幕上所有的顶层窗口,为每个窗口调用一个程序提供的函数,并传递窗口的处理程序。如果被调用者返回一个值,就继续进行迭代,否则,退出。EnumWindow()并不关心被调用者在何处,也不关心被调用者用它传递的处理程序做了什么,它只关心返回值,因为基于返回值,它将继续执行或退出。
不管怎么说,回调函数是继续自C语言的,因而,在C++中,应只在与C代码建立接口,或与已有的回调接口打交道时,才使用回调函数。除了上述情况,在C++中应使用虚拟方法或函数符(functor),而不是回调函数。
下面是一个简单的回调函数,相比其他的那些复杂的代码,这个更容易理解:
#include<stdio.h>
#include<stdlib.h>
void perfect(int n)
{
int i=1;
int count=0;
for(i=1;i<n;i++)
{
if(0==n%i)
{
count+=i;
}
}
if(count==n)
printf("%d是完数\n",n);
else printf("%d不是完数\n",n);
}
void myCallback(void (*perfect)(int ),int n)
{
perfect(n);
}
int main()
{
int n;
printf("请输入一个正整数\n");
scanf("%d",&n);
myCallback(perfect,n);
return 0;
}
关于高聚合低耦合:
2015-4-13:
聚合与耦合:
先来看看聚合的定义:聚合(Cohesion)是一个模块内部各成分之间相关联程度的度量。
这里有多个含义值得考虑。首先,聚合是对一个模块内部的度量,这也是许多情况下我们把聚合称之为内聚的原因。第二,这里出现的模块是广义的模块,它可能是子系统,可能是功能模块,也可能是功能模块中的某一个类。从不同的层次看,聚合的程度也会有所不同。至于为什么不同,后面会有解释。第三,模块的成分包括模块的行为和状态。要做到高聚合,那么模块内部的行为必须要与模块的内部状态紧密关联。通俗来讲,一个模块仅完成一个独立的功能,模块内部不存在与该功能无关的操作或状态。
再来看看耦合的定义:耦合(Couping)是模块之间相关联程度的度量。相对于聚合的内向性,耦合关注的是某一模块和其他模块之间的关联性。其实从前面的例子里,我们已经不可避免的提到了耦合的问题:由于两座城市之间的相互联系过于紧密,导致了城市之间的交通拥堵。另外一个潜在的问题就是,如果其中一座城市内部的交通出现了问题,另一座城市也会受到影响。我们所追求的低耦合,就是将两个模块之间的关联尽可能的降低,一个模块发生变化对于其他模块的影响尽可能的小。
再讲一个生活中的例子,相信大部分的80后小的时候都玩过一种掌上游戏机,这种游戏机内含一个俄罗斯方块的游戏。这种游戏机虽然风靡一时,但是不多久就渐渐淡出了市场,因为这种游戏机只有俄罗斯方块可以玩儿,当我们玩儿腻了的时候,这个游戏机也就如同废物一个了。
同期,任天堂推出一款后来风靡了将近20年的红白机,这种游戏机市场寿命如此之长并非游戏机本身质量有多好,而是因为基于红白机开发的游戏层出不穷,经典无数。魂斗罗、超级玛丽在当时哪怕是现在也是无人不知。红白机的游戏本身并不存储在游戏机当中,每当有新游戏推出的时候,只需要购买新的卡带即可。正是这种游戏机和卡带相对独立的设计,使得游戏的设计厂商无需关心游戏机的实现细节,只要遵循游戏机提供的接口(插槽)。很多游戏的设计厂商也从红白机庞大的市场中分得一杯羹。大多数的玩家可能不知道,魂斗罗并非任天堂推出的产品,而是目前以《实况足球》系列闻名世界的KONAMI公司于1988年从街机移植到红白机上的。
回到耦合的话题上来,因为早先的掌上游戏机将游戏本身内置在机器当中,游戏和机器这两个模块之间的关系过于紧密,所以游戏玩儿腻了,游戏机就没用了,游戏机出问题了,游戏也再也不能玩儿了。而红白机的游戏和游戏机之间的关系是相对独立的,只要它们都遵循制定好的协议,就可以独立的发展和变化。游戏卡带摔坏了,其他的游戏一样可以在机器上运行;自己的游戏机坏了,把卡带拿到朋友家的游戏机上也能玩儿。红白机发展到后期,连游戏机的手柄也是可插拔的,如果手柄坏了,也只需要更换手柄即可。
—————5星————————
一味的追求高内聚,必然会造成模块的功能过于单一,而模块的数量出现急剧膨胀。所以,我们在设计和实现程序时必须要斟酌模块间的聚合和耦合程度,有兴趣的朋友也可以去研究聚合性指标与耦合性指标。
//还有个java多线程-----java多线程总结
参考:http://www.cnblogs.com/rollenholt/archive/2011/08/28/2156357.html