在开发过程中,我们常常会越到这么一种case:向一个对象发送消息,每次都必须先检查对应的对象是否存在。如果对象存在执行相应操作,对象不存在则获取默认值或者做一些默认的操作。
NULL object即使这么一种模式:通过提供NULL对象,从而使客户在向对象发送消息时,不关心对象是否存在,NULL对象中保存相应的默认值或方法。
NULL object的优势个人理解:
1)降低代码复杂度
2)统一管理对象的默认值或方法
类图:
Client: 使用者
Object:使用接口
Concrete_object:client期待的real object
Null_object:do nothing 的接口类,用以替代Concrete_object
Object:使用接口
Concrete_object:client期待的real object
Null_object:do nothing 的接口类,用以替代Concrete_object
餐馆里面有很多waiter,把他们管理起来,每个waiter有个id,可以通过id给某个waiter发薪,也可以整体发薪
composite pattern + Null object pattern
代码:
#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
//object
class Emp_pay_base
{
public:
Emp_pay_base()
{
}
virtual ~Emp_pay_base()
{
}
virtual void pay() = 0;
virtual int get_id()
{
return _id;
}
protected:
int _salary;
int _id;
};
//concrete_object
class Waiter : public Emp_pay_base
{
public:
Waiter(int salary, int id)
{
_salary = salary;
_id = id;
}
virtual ~Waiter()
{
}
virtual void pay()
{
cout << "Pay waiter salary: " << _salary << endl;
}
};
//NULL object
class Null_emp : public Emp_pay_base
{
public:
Null_emp()
{
_salary = 0;
}
virtual ~Null_emp()
{
}
virtual void pay()
{
cout << "Pay salary: " << _salary << endl;
}
};
//composite
class Emp_manage : public Emp_pay_base
{
public:
Emp_manage()
{
Emp_pay_base* emp = new Null_emp();
_emp_list.push_back(emp);
}
virtual ~Emp_manage()
{
list<Emp_pay_base*>::iterator iter,tmp;
for(iter = _emp_list.begin(); iter != _emp_list.end();)
{
if(*iter)
{
tmp = iter;
iter++;
if(*tmp)
{
delete (*tmp);
*tmp = NULL;
}
}
}
}
virtual void add(int id)
{
Emp_pay_base* emp= new Waiter(2000, id);
_emp_list.push_back(emp);
}
virtual Emp_pay_base* get_emp(int search_id)
{
list<Emp_pay_base*>::iterator iter;
for(iter = _emp_list.begin(); iter != _emp_list.end(); iter++)
{
if((*iter)->get_id() == search_id)
{
return *iter;
}
}
return *(_emp_list.begin());
}
virtual void remove(Emp_pay_base* emp)
{
list<Emp_pay_base*>::iterator iter;
iter = find(_emp_list.begin(), _emp_list.end(), emp);
while(iter != _emp_list.end())
{
_emp_list.erase(iter);
}
}
virtual void pay()
{
list<Emp_pay_base*>::iterator iter;
for(iter = _emp_list.begin(); iter != _emp_list.end(); iter++)
{
(*iter)->pay();
}
}
private:
list<Emp_pay_base*> _emp_list;
};
int main(int argc, char** argv)
{
Emp_manage* emp_manage = new Emp_manage;
for(int i = 0; i <10; i++)
{
emp_manage->add(i);
}
Emp_pay_base* emp_pay1 = emp_manage->get_emp(5);
emp_pay1->pay();
//NULL object 使用
Emp_pay_base* emp_pay2 = emp_manage->get_emp(50);
emp_pay2->pay();
emp_manage->pay();
delete emp_manage;
return 0;
}
输出:
Pay waiter salary: 2000
Pay salary: 0
Pay salary: 0
Pay waiter salary: 2000
Pay waiter salary: 2000
Pay waiter salary: 2000
Pay waiter salary: 2000
Pay waiter salary: 2000
Pay waiter salary: 2000
Pay waiter salary: 2000
Pay waiter salary: 2000
Pay waiter salary: 2000
Pay waiter salary: 2000