可以解决菱形继承等问题,代码如下
#include <iostream>
#include <memory>
#include <string>
using namespace std;
struct ITask
{
virtual ~ITask(){}
virtual string GetName() = 0;
virtual void Execute() = 0;
};
/* 需求:实现logging任务 和timing任务统计,有个实际的任务myTasK类要同时要使用二者的一些相同的接口,
最直观的是采用菱形继承,但是Execute会冲突
使用组合和继承的方式
*/
/*....................................................................................
class LoggingTask : public ITask
{
std::unique_ptr<ITask> mTask;
public:
explicit LoggingTask(ITask* task):mTask(task){}
void Execute() override
{
cout << "Logging: task start " << mTask->GetName() <<endl;
if(mTask)
{
mTask->Execute();
}
cout << "Logging: task end " << mTask->GetName() <<endl;
}
string GetName() override
{
if(mTask)
{
return mTask->GetName();
}
else
{
return "unkown Logging task";
}
}
};
class TimingTask : public ITask
{
std::unique_ptr<ITask> mTask;
public:
explicit TimingTask(ITask* task):mTask(task){}
void Execute() override
{
cout << "Time is 1 " <<endl;//简单点不引入time类了
if(mTask)
{
mTask->Execute();
}
cout << "Time is 2" <<endl;
}
string GetName() override
{
if(mTask)
{
return mTask->GetName();
}
else
{
return "unkown Timeing task";
}
}
};
class MyTask : public ITask {
public:
void Execute() override {
std::cout << "...This is where the task is executed..." << std::endl;
}
std::string GetName() override {
return "My task name";
}
};
有不必要的开销:堆分配、null检查、虚函数。
像LoggingTask这样的类不想提供GetName这样的接口,但你继承自ITask就要实现这个接口。
假如ITask还有其它接口,LoggingTask都必须实现。
....................................................................................*/
/* 使用mixin方式 如下*/
template<typename T>
class LoggingTask : public T
{
public:
void Execute()
{
cout << "Logging: task start " << T::GetName() <<endl;
T::Execute();
cout << "Logging: task end " << T::GetName() <<endl;
}
};
template<typename T>
class TimingTask : public T
{
public:
void Execute()
{
cout << "Time is 1 " <<endl;
T::Execute();
cout << "Time is 2" << endl;
}
};
class MyTask {
public:
void Execute() {
std::cout << "...This is where the task is executed..." << std::endl;
}
std::string GetName() {
return "My task name";
}
};
//Task管理框架,因为它没实现ITask接口,这就是最后一个mixin的功能
template<typename T>
class TaskAdpter : public ITask, public T
{
public:
void Execute() override
{
T::Execute();
}
string GetName() override
{
return T::GetName();
}
};
int main()
{
/* 组合加继承的方式
unique_ptr<ITask> task(new LoggingTask(new TimingTask(new MyTask())));
task->Execute();
*/
MyTask t1;
t1.Execute();
TimingTask<MyTask> t2;
t2.Execute();
// A MyTask with added logging and timing:
LoggingTask<TimingTask<MyTask>> t3;
t3.Execute();
// A MyTask with added logging and timing written to look a bit like the composition example
using Task = LoggingTask<TimingTask<MyTask>> ;
Task t4;
t4.Execute();
using LTMTask = TaskAdpter<LoggingTask<TimingTask<MyTask>>> ;
LTMTask t;
ITask* t5 = &t;
t5->Execute();
getchar();
return 0;
}