定义:

单来源调用指一个类的生成工作只能由特定类来执行。

eg李宁牌鞋子只能由李宁专卖店生产

这个问题归结起来,也就是说在工厂模式中,指定的产品类只能通过具体的特定工厂类来生成,而不能自己new出来或者通过其他类生成。

具体的,我们就在代码实现中进行说明了。

这里我们来一步一步分析。

首先,一个类实例(对象)不能自己产生,那么。我们就需要屏蔽构造函数了。

那么,屏蔽了构造函数之后,如何获取一个实例呢。

有两种方案可以实现。

方案一:

通过继承获取构造函数执行权限。如代码

class base
{
protected:
base()
{
Trace("");
}
};
class driver:protected base
{
public:
void test()
{
base b;
}
}; int main(int argc, char const *argv[])
{
driver d;
d.test();
return ;
}

这个方案只是可以让一个类能够产生实例。单他和我们的意图严重偏离:

a实例和子类的生命周期一致。

b没有自主权。

c其他类也可以模拟他的实现,继承父类获取生成权,这显然是个垃圾方案。

方案二:类似单例模式方法处理

产品类 构造函数屏蔽,但是提供一个获取实例的共有方法

静态方法获取实例
class base
{
protected:
base()
{
Trace("");
}
public:
static base* getInstance();
}; base* base::getInstance()
{
return new base();
}
int main(int argc, char const *argv[])
{
// base* p = new base();
base * p = base::getInstance();
return ;
}

通过方案二,我们实现了一个类不能自己执行 base *p = new base()

类型绑定

那么下面我们的目标就是将这个产品类和具体可生产者进行绑定了。

如何绑定呢,对于一个特定的类,处理之,我们就想到了this指针

所以我们要做的就是,产品类构造函数依赖工厂类的this 指针

// 通过静态方法获取,且依赖driver的this指针。
// 但是此时也可以通过临时对象driver生成
class driver;
class base
{
protected:
base()//driver*)
{
Trace("");
}
public:
static base* getInstance(driver*);
}; base* base::getInstance(driver*)
{
return new base();
} class driver
{
public:
base* getInstance()
{
return base::getInstance(this);
}
};
int main(int argc, char const *argv[])
{ base * p = (driver()).getInstance(); //我们所期望的运行方式。
p = base::getInstance(new driver()); //产品类抓住漏洞强行生成自我
return ;
}

到这里,貌似我们的目标已经达到了,但是呢。如例子中的  p = base::getInstance(new driver());这个方法,本质还是base类自主生成的。

并不能符合我们的要求。

那么到这里,我们应该如何处理呢。

我能想到的就是,不光让base建立依赖driver的this指针,同时设置权限。才能执行getinstace()

首先给出最终代码了

// 抽象接口类,提供子类行为,同时定义权限值以及权限判断给base中的getinstace方法使用
class abstractDriver
{
protected:
bool _canCreate;
abstractDriver(bool can)
:_canCreate(can)
{}
public:
virtual bool canCreate(){
return _canCreate;
}
}; class base
{
protected:
base()
{
Trace("");
}
public:
static base* getInstance(abstractDriver*);
}; // 根据依赖的this对应类是否有权限执行决定生成
base* base::getInstance(abstractDriver*dr)
{
if (dr->canCreate())
/* code */
return new base();
else
return NULL;
} class driver:public abstractDriver
{
public:
driver()
:abstractDriver(false)
{
Trace("");
}
//在获取base实例前后修改权限。保证外部权限始终伪假
base* getInstance()
{
_canCreate = true;
base* p =base::getInstance(this);
_canCreate = false;
return p;
}
}; int main(int argc, char const *argv[])
{
base* p = base::getInstance(new driver());
cout << p <<endl; //NULL,未生成实例
p = (driver()).getInstance();
cout << p <<endl;
p = (driver()).getInstance();
cout << p <<endl;
return ;
}

好了,最终的实现版本就完成了。

符合我们的目标

base类只能通过driver类生成。

最后,我们可以发现,这个实现中的getInstace方法让我们想到了单例模式的实现。

不同的是单例模式的结果是最终

a只有一个类型实例产生,

b生成方式可以是自主的 base::getinstance()

而我们的单来源调用,

a。生成实例个数不一定是一个,只是生成方式限定了

b。不能通过直接调用base::getinstance()生成。

之所以拿出来将两个模式进行比较,是因为:单来源调用并不是23种设计模式中的一种,初次看他时,我自己也是一脸蒙蔽。其次,两者都是很重要,很常用的方法。

个人源码实现github地址:https://github.com/langya0/design_pattern_study/tree/master/singleCall

23种设计模式C++实现及扩展代码:https://github.com/langya0/design_pattern_study

参考《Single Call 模式

最新文章

  1. [下载]北京新版小学英语五年级上册mp3点读APP
  2. 按照TYPE的文件导入导出功能
  3. [WCF编程]12.事务:事务传播
  4. MVC5+EF6 入门完整教程十
  5. 第一个jemter测试脚本
  6. C#模拟键盘输入(一)
  7. BZOJ4531: [Bjoi2014]路径
  8. 2013 ACM 通化邀请赛D.D-City 并查集
  9. IOSSelector的用法
  10. java properties 文件中书写相对路径
  11. C++11中新特性之:lambda 表达式
  12. Bootstrap兼容处理
  13. Docker基础入门及示例
  14. HDU - 1043 A* + 康托 [kuangbin带你飞]专题二
  15. STS(Spring Tool Suite)下SSM(Spring+SpringMVC+Mybatis)框架搭建(一)
  16. Codeforces 840C On the Bench dp
  17. [P2850][USACO06DEC]虫洞Wormholes (最短路)
  18. 边框回归(Bounding Box Regression)详解
  19. 添加全局函数$.extend和对象方法$.fn
  20. Hbase 学习(四) hbase客户端设置缓存优化查询

热门文章

  1. 通过js获得选择文件的绝对路径
  2. NYOJ 1023 还是回文(DP,花最少费用形成回文串)
  3. Yii的学习(3)--查询生成器 (Query Builder)
  4. AngularJS的学习--$on、$emit和$broadcast的使用
  5. Unity中 动态加载 Resources.Load()和Asset Bundle 的区别
  6. 云计算之路-阿里云上:结合IIS日志分析“黑色30秒”问题
  7. Linux 启动过程分析
  8. 微信支付v3发布到iis时的证书问题
  9. java设计模式(二)---工厂方法模式
  10. 四、BLE(中)