李普曼C++底漆中的设计模式
Design Pattern in Lippman's C++ Primer
我对编程还很陌生,所以如果答案显而易见,请耐心回答我的问题。
在Lippman、Lajoie和Moo的《C++入门》第五版第15.9节中,该节涉及到对继承层次结构的编程。它基本上是一个抽象类Query_base
,其子类是WordQuery
、NotQuery
和BinaryQuery
,最后一个分支为AndQuery
和OrQuery
。Query_base
层次结构由一个名为Query
的接口类通过指针访问。此设置背后的基本思想是使用如下的复合查询:
Query q = Query("fiery") & Query("bird") | Query("wind")
(这些运算符生成指向Query_base
类型对象的Query
对象,例如,"&
"生成AndQuery
,"~
"生成NotQuery
然后可以在文本文档中搜索符合查询规则的行。)
Query_base类如下:
class Query_base {
friend class Query;
protected:
virtual ~Query_base() = default;
private:
virtual QueryResult eval(const TextQuery&) const = 0;
virtual std::string rep() const = 0;
}
所有Query_base子级都实现了eval()和rep(),因此都是可实例化的。
Query类的设计如下:
class Query {
friend Query operator~(const Query&);
friend Query operator|(const Query&, const Query&);
friend Query operator&(const Query&, const Query&);
public:
Query(const std::string&);
QueryResult eval(const TextQuery &t) const { return q->eval(t); }
std::string rep() const { return q->rep(); }
private:
Query(std::shared_ptr<Query_base> query) : q(query) { }
std::shared_ptr<Query_base> q;
所以我的理解是,设计有一个继承层次结构,然后是一个故意相互分离的接口。后者从侧面访问前者,而不仅仅是让基类作为接口。
我有两个问题:
- 没有单独的
Query
类有什么问题吗?我们可以让Query_base
类同时作为层次结构和接口的基础,并去掉Query
类吗?我认识到,正如Query_base
所代表的那样,它不能,因为它有纯粹的虚拟功能,但这些功能可以改变。例如,我不能把eval()
和rep()
的Query
函数实现转移到Query_base
吗?这样做有什么不对吗?Query
中的shared_ptr<Query_base>
是否使事情复杂化,并且是分离的基础?如果是,我们可以解决这个问题吗 - 像这样的层次结构接口分离有多常见(如果这是正确的想法)
提前感谢!
如果我们继续实现所有这些运算符和其他子查询类型,那么分离的必要性就变得显而易见了。让我们想象一下,例如;操作员可能看起来像。
&
运算符应该构造一个查询,而该查询又应该包含另外两个查询。因此,AndQuery
类可以这样定义:
class AndQuery: public BinaryQuery {
public:
AndQuery(const Query_base& lhs, const Query_base& rhs);
AndQuery(Query_base&& lhs, Query_base&& rhs);
...
QueryResult eval(const TextQuery& t) override;
private:
// required members and private methods...
// two principal members, lhsQuery and rhsQuery for
// left hand side subquery and light hand side subquery
// correspondingly are defined in `BinaryQuery`
};
并且,在一个简单的未优化的情况下,AndQuery
应该以某种方式执行搜索(eval()
),如下所示:
QueryResult AndQuery::eval(const TextQuery& t) {
QueryResult lhsResult = lhsQuery.eval(t);
QueryResult rhsResult = rhsQeury.eval(t);
// the resulting ResultSet should include only entries
// from both result sets
for(auto it = lhsResult.begin(); it != lhsResult.end(); ++it)
if (rhsResult.find(*it) == rhsResult::cend())
it = lhsResult.erase(it);
// now we can return lhsResult because we have erased all elements from it
// which weren't in rhsResult
return lhsResult;
}
其他查询组件子类有自己的特定实现。反过来,Query
有自己的一组特定方法,比如从字符串构造查询。如果没有纯虚拟的Query_base
,我们必须与所有组件子类共享Query
的实现细节。此外,我们还必须让这些类对外部用户可见。
通过使用单独的"接口"Query
类,我们为子系统的用户提供了一个清晰易懂的精益接口。
除了上面的注释之外,我认为这个设计还与c++中的多态性有关,它只通过引用和指针来支持,而不是对象本身。
通过使用";查询";对象和一个嵌入的智能指针指向具有层次结构和多态性的Query_Base,类的用户可以使用Query对象来实现多态性效果。
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 资源管理设计模式
- 用于在回调中调用解析器的设计模式
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 在这种情况下我应该使用哪种设计模式
- C++中物体改变识别的设计模式?
- 确保所有构造函数调用相同的函数 c++ 设计模式
- 需要实例化不同类/对象并在启动时确定的硬件插槽的设计模式
- 设计模式,以避免不必要地添加抽象函数以适应新功能
- 工厂设计模式优化
- 使用C++模板的数据映射器设计模式
- 为什么以及如何使用原型设计模式
- 具有多个继承共享一个资源的对象 - 寻找良好的设计模式
- 在C++中创建观察器设计模式的好方法
- 现代C++在多大程度上消除了对设计模式的需求?
- 对于存储另一个类所需信息的类,例如其构造,是否有设计模式?
- 下面抽象工厂设计模式的实现是正确的吗
- sql记录集函数的状态设计模式
- 是否有可以处理方法调用依赖关系的设计模式?
- 使用 C++ 设计模式