- 文件和目录的设计.
- 首先,必须有两个对象,File和Directory.
- 想以相同的方式处理文件和目录,所以必须有一个共通的接口Node.
- 对于以相同的方式处理那些不能适用于两者的操作时.
- 例如:Node GetChild(n).必须返回Node类型以在返回值上再次调用GetChild.也就要求必须在Node接口上定义该方法.
- 适用Composite模式的关键:想要表示对象的"部分-整体"层次结构,树结构支持任意的复杂度,以统一的方式处理结构中的对象.
- .
- Composite的坏处:每个对象的类和其他对象的类没有区别.区别只能在运行时才显露.
- 存储子节点时,应使用什么数据结构.
- 是否应该在Component类中声明添加和删除子节点的操作.
- 文件的创建和添加.
- 首先,文件的创建应该是用户的责任.目录只负责收养子节点. void adopt(Node Child).
- 相应地,目录可以解除该责任.void orphan(Node Child).但此时该节点依然存在,只是不属于该目录而已.
- 对于mkdir命令,传入的是一个路径,我们必须递归处理该路径,然后在最后一层上创建新目录,并收养它.
- 问题在于递归处理路径时,调用Node节点的GetChild来检查该Node是否有对应的子路径,返回的是Node类型,因为深入文件系统层次时,我们并不知道是文件还是目录.
- 所以,我们还是必须把adopt和orphan方法定义在Node上.只是Node中默认实现为抛出异常(或者其它的,代表不能进行该操作的).
- 然后在mkdir函数中,对于递归处理路径的结果,判断是否是目录,如果是目录就递归调用mkdir,如果是文件,就抛出异常(不正确的传入路径).
- 这就带来了不统一性的问题.但是对于这种不允许在Leaf上调用Leaf有关的操作时,是必须的.编译器必须知道这种区别.
- 这种不统一性,通常会带来简单性和扩展性.
- 引入代用品(快捷方式)
- 模式的选择:
- 考虑设计中那些部分是可变的
- 看那些模式的目的与要解决的问题对应.
- 我们选择Proxy模式:当我们需要对一个对象进行引用,但是该引用需要具备比简单指针更复杂的功能时.
- Proxy的接口和Subject一致,所以能替代任何的Subject对象.Node代表了Subject对象.
- 新增一个继承自Node的Link类来代表Proxy,其内部有一个Node类型的对象指向RealSubject.(因为File和Directory有相同的接口.)
- 不对已有类进行改动就添加新操作.访问权限.
- Node现在承担了两种模式的责任,组件和代理模式.这是"密集"复合模式.可能会造成一个模式被实现后,可能丢失的问题.
- Node接口的关键是找出一组基本够用的最小的操作集合.
- 但是对于那么要以不同的方式处理不同的节点类型的操作.例如输入内容的cat命令.File和Directory会有不同的行为.我们为了引入该操作,必须修改既存的类?
- 我们也可以把该功能放入客户端代码,但是这样做的话,必须在该代码中进行向下转型.这太恶心了.
- 使用Visitor模式:表示一个用来处理某对象结构中各个元素的操作.无需修改待处理元素的类,就可以定义新的操作.
- 首先,在Node类中定义void accept(Vistor v).
- 然后,在各个子类中分别实现{v.visit(this);}.虽然3个子类的实现代码一样,但是由于this是不一样的,所以效果是不一样的.
- 再然后,在Class Visitor{ visit(File);visit(Directory);visit(Link);}.
- 客户端代码: Visitor cat; node.accept(cat);
- 当我们想添加另外的功能时.
- 首先,Visitor是一个接口.
- 然后,对于每一中功能,派生一个Visitor出来.
- 我们可以将Visitor接口中的3个重载函数重新定义.VisitFile(File);VisitDirectory(Directory);VisitLink(Link);
- Visitor模式的问题:
- 被访问的类层次结构是否稳定?是否会经常定义新的Node子类,这会代理修改Visitor类层次中的所有类.
- 如果所有的visitor对新的Node子类都不感兴趣,那么可以在VisitNode函数中进行默认处理.
- 但是只有一中类型的visitor对新子类感兴趣是,我们至少要修改该visitor和visitor基类.
- Visitor和Node类层次结构之间创建了循环依赖关系.任何一个基类的接口修改.都得重新编译.
- 单用户文件系统的保护
- 对不可写的节点进行保护,使之无法删除.我们采用了对析构函数进行保护的方法.声明为protected,这样在Node类层次结构之外的类是无法删除一个Node的.
- 谁来定义删除操作?在Node基类中定义destroy.
- 模板方法:将destroy定义为