一个一对多问题的设计模型

    问题引入:

        今天在做一个用来限制对象位置的功能类,要完成的任务就是当对象被拖动的时候,不允许超出工作区域多少距离。这个问题不好处理的地方就是这个工作区域的获取问题,因为无法知道工作区域发生更改,并且工作区域更改的地方也无法直接设置给对象,即使能设置,也无法设置给这么多对象。因此这就是一个简单的一对多问题,即一个变化需要引起多个的变化。

    问题引出:

       简化一下上述问题。有一个对象CSample,其内部有一个属性miCount需要根据一个系统相关的属性miSystemValue来进行计算。在无法直接接收到这个系统属性发生更改的前提下,如何让其所有实例化出来的对象都能重新进行计算呢?(注:下面的代码没进行编译,随便写了下例子方便说明。)

class CSample
{
	public:
		CSample();
		~CSample();

		int GetCount()
		{
			return miCount;
		}

	protected:
		MakeCount(){miCount = miValue + miSystem;}

	private:
		int miCount;
		int miValue;
		int miSystem;   // 系统所提供的一个参数,全系统都唯一的
}

int main()
{
	CSample loSample1;
	CSample loSample2;
	CSample loSample3;

	cout << loSample1.GetCount << endl;
	cout << loSample2.GetCount << endl;
	cout << loSample3.GetCount << endl;
	

	// 假设这时候miSystem发生了变化
	// 如何让上述三个对象重新计算其内部的miCount的值?
	
	return 0;
}


    解决办法:

1、主动索取方式。

        所有实例化出来的对象,每次在计算的时候都直接主动去获取系统的这个参数,这样不管多少个实例,系统参数如何改变都能保证正确。假如GetSystemValue是获取系统参数的函数,则只需写成miCount = miValue + GetSystemValue()即可。

    好,下面问题来了。

        1、如果无法直接获取到系统参数怎么办?

        2、如果这种计算效率很低,要求优化,怎么办?

        问题1是这个方法最不好解决的地方,因为这个方法就是假设能直接获取的基础上,这里提出这个问题是方便后面的方法能考虑到这个问题。问题2有一定的优化方式,就是自己记住旧的系统参数,每次进行计算前进行判定需不需要重新计算,这样能避免每次都无厘头的进行计算,但是效率效果还不是很好。

2、提供静态函数。

         类的静态函数只能操做静态变量,因此系统参数作为静态变量存储在类内部,所有实例化的类共享这个变量,注意要传进去类的实例化指针,才能操纵非静态成员变量。这里是重新计算miCount值。

      对于上面提到的两个问题,这种方式都比较好的进行了解决。但是这中方法有个缺陷就是在获取到系统参数更改的地方,必须拥有所有实例化的对象指针,不然如何在这里调用这个静态函数的同时传入对象指针呢?因此,问题3来了。

      如果实例化的对象位置无法预知,怎么办?

3、提供一个管理器。

        上述3个问题,要想同时解决,那么需要满足的条件有:类需要提供函数去被动触发进行计算,不能任何时候都计算,以及需要将所有实例化的对象集中起来进行管理。一种好的解决方式是,提供一个全局的容器,在对象的构造函数内主动加入到容器中去,当系统参数发生更改的时候,遍历容器去调用触发计算的接口。

 

         后记:本来看起来很简单的一个功能,在实际实现的时候才发现因素导致很多方法不适用,其实归根到底就是程序灵活性的问题。

posted on 2012-11-02 22:57  好好单调  阅读(399)  评论(0编辑  收藏  举报