您的位置:首页 > 其它

结构型对象设计模式

2007-05-01 11:02 435 查看
结构型对象模式采用继承机制来组合接口或实现。它不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法。因为可以在运行时刻改变对象组合关系,所以对象组合具有更大的灵活性,而这种机制用静态组合是不能实现的。

ADAPTER(适配器)<Wrapper包装器>
意图将一个类的接口转换成客户希望的另外一个接口。它使得原本由于借口不兼容而不能一起工作的那些类可以一起工作。

适用性
#想使用一个已经存在的类,而它的接口不符合你的要求;
#想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
#想使用一些已经存在的子类,但不可能对每一个都进行子类化以匹配它们的接口,对象适配器可以适配它的父类接口(仅适用于对象Adapter)。

BRIDGE(桥接)<Handle/Body>
意图----将抽象部分与它的实现部分分离,使它们都可以独立变化

适用性
#不希望在抽象和它的实现部分之间有一贯固定的绑定关系。例如这种原因可能是因为在程序运行时刻实现部分应可以被选择或切换。
#类的抽象以及它的实现部分都应该可以通过生成子类的方法加以扩充。这时该模式可以对不同的接口和实现部分进行组合,并分别对它们进行扩充。
#对一个抽象的实现部分的修改应对客户不产生影响,机客户的代码不必重新编译。
#想对客户完全隐藏抽象的实现部分。C++中,类的表示在类接口中是可见的。
#想在多个对象间共享实现(可能使用引用计数),但同时要求客户并不知道这一点。

COMPOSITE(组合)
意图---将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

适用性
#想表示对象的部分-整体层次结构
#希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。

实例:
#ifndef COMPOSITE_H
#define COMPOSITE_H
#include <list>
class Component // 组合中的抽象基类
{
public:
Component(){}
virtual ~Component(){}
virtual void Operation() = 0;
virtual void Add(Component* pChild);
virtual void Remove(Component* pChild);
virtual Component* GetChild(int nIndex);
};
// 派生自Component,是其中的叶子组件的基类
class Leaf : public Component
{
public:
Leaf(){}
virtual ~Leaf(){}
virtual void Operation();
};
// 派生自Component,是其中的含有子件的组件的基类
class Composite : public Component
{
public:
Composite(){}
virtual ~Composite();
virtual void Operation();
virtual void Add(Component* pChild);
virtual void Remove(Component* pChild);
virtual Component* GetChild(int nIndex);
private:
// 采用list容器去保存子组件
std::list<Component*> m_ListOfComponent;
};
#endif

#include "Composite.h"
#include <iostream>
#include <algorithm>
void Component::Add(Component* pChild)
{ }
void Component::Remove(Component* pChild)
{ }
Component* Component::GetChild(int nIndex)
{ return NULL; }
void Leaf::Operation()
{ std::cout << "Operation by leaf/n"; }
Composite::~Composite()
{
std::list<Component*>::iterator iter1, iter2, temp;
for (iter1 = m_ListOfComponent.begin(), iter2 = m_ListOfComponent.end();iter1 != iter2;
)
{
temp = iter1;
++iter1;
delete (*temp);
}
}
void Composite::Add(Component* pChild)
{
m_ListOfComponent.push_back(pChild);
}
void Composite::Remove(Component* pChild)
{
std::list<Component*>::iterator iter;
iter = find(m_ListOfComponent.begin(), m_ListOfComponent.end(), pChild);
if (m_ListOfComponent.end() != iter)
{
m_ListOfComponent.erase(iter);
}
}
Component* Composite::GetChild(int nIndex)
{
if (nIndex <= 0 || nIndex > m_ListOfComponent.size())
return NULL;
std::list<Component*>::iterator iter1, iter2;
int i;
for (i = 1, iter1 = m_ListOfComponent.begin(), iter2 = m_ListOfComponent.end();iter1 != iter2;++iter1, ++i)
{
if (i == nIndex)
break;
}
return *iter1;
}
void Composite::Operation()
{
std::cout << "Operation by Composite/n";
std::list<Component*>::iterator iter1, iter2;
for (iter1 = m_ListOfComponent.begin(), iter2 = m_ListOfComponent.end();iter1 != iter2;++iter1)
{
(*iter1)->Operation();
}
}

#include "Composite.h"
#include <stdlib.h>
int main()
{
Leaf *pLeaf1 = new Leaf();
Leaf *pLeaf2 = new Leaf();
Composite* pComposite = new Composite;
pComposite->Add(pLeaf1);
pComposite->Add(pLeaf2);
pComposite->Operation();
pComposite->GetChild(2)->Operation();
delete pComposite;
system("pause");
return 0;
}

DECORATOR(装饰)<包装器Wrapper>
意图----动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。

适用性
#在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
#处理那些可以撤消的职责。
#当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一个组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

实例
#ifndef DECORATOR_H
#define DECORATOR_H
// 抽象基类,定义一个对象接口,可以为这个接口动态的添加职责.
class Component
{
public:
Component(){}
virtual ~Component(){}
virtual void Operation() = 0;
};
// 抽象基类,维护一个指向Component 对象的指针
class Decorator : public Component
{
public:
Decorator(Component* pComponent) : m_pComponent(pComponent){}
virtual ~Decorator();
protected:
Component* m_pComponent;
};
// 派生自Component,在这里表示需要给它动态添加职责的类
class ConcreateComponent : public Component
{
public:
ConcreateComponent(){}
virtual ~ConcreateComponent(){}
virtual void Operation();
};
// 派生自Decorator,这里代表为ConcreateComponent动态添加职责的类
class ConcreateDecorator : public Decorator
{
public:
ConcreateDecorator(Component* pComponent) : Decorator(pComponent){}
virtual ~ConcreateDecorator(){}
virtual void Operation();
private:
void AddedBehavior();
};
#endif

#include "Decorator.h"
#include <iostream>
Decorator::~Decorator()
{
delete m_pComponent;
m_pComponent = NULL;
}
void ConcreateComponent::Operation()
{
std::cout << "Operation of ConcreateComponent/n";
}
void ConcreateDecorator::Operation()
{
m_pComponent->Operation();
AddedBehavior();
}
void ConcreateDecorator::AddedBehavior()
{
std::cout << "AddedBehavior of ConcreateDecorator/n";
}

#include "Decorator.h"
#include <stdlib.h>
int main()
{
// 初始化一个Component对象
Component* pComponent = new ConcreateComponent();
// 采用这个Component对象去初始化一个Decorator对象,
// 这样就可以为这个Component对象动态添加职责
Decorator* pDecorator = new ConcreateDecorator(pComponent);
pDecorator->Operation();
delete pDecorator;
system("pause");
return 0;
}

FAÇADE(外观)
意图----为子系统中一组接口提供一个一致的界面,该模式定义了一个高层接口,这个接口使得这一子系统更加他、容易使用。

适用性
#当要为一个复杂子系统提供一个简单接口时,子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类。这使得子系统更具有可重用性,也更容易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困难。Façade模式可以提供一个简单的却省视图,这一视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过façade层。
#客户程序与抽象类的实现部分之间存在着很大的依赖性。引入façade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性和可移植性。
#当需要构建一个层次结构的子系统时,使用façade模式定义子系统中每层的入口点。若子系统之间是相互依赖的,可以让它们仅通过façade进行通讯,从而简化了它们之间的依赖关系。

实例

FLYWEIGHT(享元)
意图----运用共享技术有效地支持大量细粒度的对象。

适用性—FlyWeight模式的有效性很大程度上取决与如何使用它们及在何处使用它。
#一个应用程序使用了大量对象。
#完全由于使用大量的对象,造成很大的存储开销。
#对象的大多数状态都可以变为外部状态。
#若删除对象的外部状态,则可以用相对较少的共享对象取代很多组对象。
#应用程序不依赖于对象标识。由于FlyWeight对象可以被共享,对于概念上明显有别的对象,标识测试将返回真值。

实例
#ifndef FLYWEIGHT_H
#define FLYWEIGHT_H
#include <string>
#include <list>
typedef std::string STATE;
class Flyweight
{
public:
virtual ~Flyweight(){}
STATE GetIntrinsicState();
virtual void Operation(STATE& ExtrinsicState) = 0;
protected:
Flyweight(const STATE& state):m_State(state){}
private:
STATE m_State;
};
class FlyweightFactory
{
public:
FlyweightFactory(){}
~FlyweightFactory();
Flyweight* GetFlyweight(const STATE& key);
private:
std::list<Flyweight*> m_listFlyweight;
};
class ConcreateFlyweight : public Flyweight
{
public:
ConcreateFlyweight(const STATE& state): Flyweight(state){}
virtual ~ConcreateFlyweight(){}
virtual void Operation(STATE& ExtrinsicState);
};
#endif

#include "FlyWeight.h"
#include <iostream>
inline STATE Flyweight::GetIntrinsicState()
{
return m_State;
}
FlyweightFactory::~FlyweightFactory()
{
std::list<Flyweight*>::iterator iter1, iter2, temp;
for (iter1 = m_listFlyweight.begin(), iter2 = m_listFlyweight.end();
iter1 != iter2;
)
{
temp = iter1;
++iter1;
delete (*temp);
}
m_listFlyweight.clear();
}
Flyweight* FlyweightFactory::GetFlyweight(const STATE& key)
{
std::list<Flyweight*>::iterator iter1, iter2;
for (iter1 = m_listFlyweight.begin(), iter2 = m_listFlyweight.end();
iter1 != iter2;
++iter1)
{
if ((*iter1)->GetIntrinsicState() == key)
{
std::cout << "The Flyweight:" << key << " already exits"<< std::endl;
return (*iter1);
}
}
std::cout << "Creating a new Flyweight:" << key << std::endl;
Flyweight* flyweight = new ConcreateFlyweight(key);
m_listFlyweight.push_back(flyweight);
}
void ConcreateFlyweight::Operation(STATE& ExtrinsicState)
{
}
int main()
{
FlyweightFactory flyweightfactory;
flyweightfactory.GetFlyweight("hello");
flyweightfactory.GetFlyweight("world");
flyweightfactory.GetFlyweight("hello");
system("pause");
return 0;
}

PROXY(代理)<Surrogate>
意图为其他对象提供一种代理以控制对这个对象的访问。

适用性需要用比较通用和复杂的对象指针代替简单的指针时,可以使用Proxy模式.
#远程代理(Remote Proxy)为一个对象在不同的地址空间提供局部代表。
#虚代理(Virtual Porxy)根据需要创建开销很大的对象。
#保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限时。
#智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。它的典型用途包括:
##对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它(也称为Smart Pointer.
##当第一次引用一个持久对象时,将它装入内存。
##在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

实例
#ifndef PROXY_H
#define PROXY_H
// 定义了ProxyRealSubject的公有接口,
// 这样就可以在任何需要使用到RealSubject的地方都使用Proxy.
class Subject
{
public:
Subject(){}
virtual ~Subject(){}
virtual void Request() = 0;
};
// 真正使用的实体
class RealSubject : public Subject
{
public:
RealSubject();
virtual ~RealSubject(){}
virtual void Request();
};
// 代理类,含有一个指向RealSubject对象的指针
class Proxy : public Subject
{
public:
Proxy();
virtual ~Proxy();
virtual void Request();
private:
RealSubject* m_pRealSubject;
};
#endif

#include "Proxy.h"
#include <iostream>
RealSubject::RealSubject()
{
std::cout << "Constructing a RealSubject/n";
}
void RealSubject::Request()
{
std::cout << "Request By RealSubject/n";
}
Proxy::Proxy() : m_pRealSubject(NULL)
{
std::cout << "Constructing a Proxy/n";
}
Proxy::~Proxy()
{
delete m_pRealSubject;
m_pRealSubject = NULL;
}
void Proxy::Request()
{
// 需要使用RealSubject 的时候才去初始化
if (NULL == m_pRealSubject)
{
std::cout << "Request By Proxy/n";
m_pRealSubject = new RealSubject();
}
m_pRealSubject->Request();
}

#include "Proxy.h"
#include <stdlib.h>
int main()
{
Subject* pProxy = new Proxy();
pProxy->Request();
delete pProxy;
system("pause");
return 0;
}

总结
AdapterBridge
AdapterBridge具有一些共同特征。它们都给另一个对象提供了一定程序上的间接性,因而有利于系统的灵活性。它们都涉及到从自身以外的一个接口向这个对象转发请求。
Adapter模式主要是为了解决两个已有接口之间不匹配的问题。它不考虑这些接口是怎么实现的,也不考虑它们各自可能会如何演化。这种方式不需要对两个独立设计的类中的任一个进行重新设计,就能使它们协同工作。Bridge模式则对抽象接口与它的(可能是多个)实现部分进行桥接。虽然这一模式允许修改它的实现,它仍然为用户提供了一个稳定的接口。Bridge模式也会在系统演化时适应新的实现。
由于这些不同点,AdapterBridge模式通常用于软件生命周期的不同阶段。当发现两个不兼容的类必须同时工作时,就有必要使用Adapter模式,其目的一般是为了避免代码重复。此处耦合不可预见。相反,Bridge的使用者必须知道,一个抽象将多个实现部分,并且抽象和实现两者是独立演化的。Adapter模式在类已经设计好后实施;而Bridge模式在没有设计类之前实施。这并不意味者Adapter模式不如Bridge,只是因为它们针对不同的问题。
可能认为façade是另外一组对象的适配器,但这种解释忽略了一个事实:即Façade定义一个新的接口,而Adapter则复用一个原有的接口。

Composite,DecoratorProxy
CompositeDecorator都是基于递归组合来组织可变数目的对象。它们的相似点仅止于递归组合。Decorator旨在能够不需要生成子类即可给对象添加职责。这就避免了静态实现所有功能组合,从而导致子类急剧增加。Composite则有不同的目的,它旨在构造类,使多个相关的对象能够以统一的方式处理,而多重对象可以被当作一个对象来处理。它重点不在于修饰,而在于表示。
尽管它们的目的截然不同,但却具有互补性。因此CompositeDecorator模式通常协同使用。在使用这两种模式进行设计时,我们无须定义新的类,仅需要将一些对象插接在一起即可构建应用,这时系统中将回有一个抽象类,它有一些composite子类和decorator子类,还有一些实现系统的基本构建模块。此时,compositedecorator将拥有共同的接口。从Decorator模式的角度看,composite实际一个ConcreteComponent;而从composite模式看,decorator则是一个Leaf
DecoratorProxy模式都描述了怎样为对象提供一定程度上的间接引用,它们对象的实现部分都保留了指向另一个对象的指针,它们向这个对象发送请求。像Decorator模式一样,Proxy模式构成一个对象并为用户提供一致的接口,但与Decorator模式不同发是,Proxy模式不能动态地添加或分离性质。它也不是为递归组合而设计的。它的目的是,当直接访问一个实体不方便或不符合需要时,为这个实体提供一个替代者。例如,实体在远程设备上,访问受限制或实体是持久存储的。
Proxy模式中,实体定义了关键功能,而Proxy提供(或拒绝)对它的访问。在Decorator模式中,组件仅提供了部分功能,而一个或多个Decorator负责完成其他功能。Decorator模式适用于编译时不能(至少不方便)确定对象的全部功能的情况。这种开放性使递归组合为Decorator模式中一个必不可少的部分。而在Proxy模式则不是这样,因为Proxy模式提供强调一种关系(Proxy和它的实体之间的关系),这种关系可以静态的表达。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: