Contents

设计模式总结二

结构型模式主要有:适配器模式,装饰模式,桥接模式,组合模式,享元模式,代理模式,外观模式

2.1 适配器模式 (Adapter)

特点

将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

应用场景

  • a.使用一个已经存在的类,而它的接口不符合你的需求时

  • b.当你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作时

  • c.想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口(仅适用于对象Adapter)

UML图

/images/design_pattern2_1.png

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/* 适配器模式 */
class Adaptee
{
public:
    void SpecificRequest()
    {
        std::cout << "SpecificRequest" << std::endl;
    }
};

class Target
{
public:
    virtual void Request()
    {
        std::cout << "Request" << std::endl;
    }
};

class Adapter: public Target
{
public:
    void Request() override
    {
        adapter.SpecificRequest();
    }
private:
    Adaptee adapter;
};

int main()
{
    Target *target = new Adapter();
    target->Request();
    return 0;
}

// 类适配器
class Adaptee
{
public:
    virtual void SpecificRequest()
    {
        std::cout << "SpecificRequest" << std::endl;
    }
};

class Target
{
public:
    virtual void Request()
    {
        std::cout << "Request" << std::endl;
    }
};

class Adapter: public Target,private Adaptee
{
public:
    void Request() override
    {
        Adaptee::SpecificRequest();
    }
};

int main()
{
    Target *target = new Adapter();
    target->Request();
    return 0;
}

优点

  • a.使得可以Adapter可以重定义Adaptee的部分行为
  • b.允许一个Adapter与多个Adaptee(即Adaptee本身以及它的所有子类)一同工作

缺点

  • a.使用一个具体的类对Adapter类对Adaotee和Target进行匹配,无法灵活使用Adapter的子类
  • b.使得重定义Adaptee的全部行为比较困难

2.2 装饰模式 (Decorator)

特点

动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

应用场景

  • a.在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责

  • b.处理那些可以撤销的职责

  • c.当不能采用生成子类的方法进行扩充时

UML图

/images/design_pattern2_2.png

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/* 装饰器模式 */
class Component
{
public:
    virtual void Operation() = 0;
};

class ConcreteComponent:public Component
{
public:
    void Operation() override
    {
        std::cout << "base operation" << std::endl;
    }
};

class Decorator: private Component
{
public:
    void SetComponent(Component *component)
    {
        component_ = component;
    }
    void Operation() override
    {
        if(component_ != nullptr)
        {
        component_->Operation();
        }
    }
protected:
    Component *component_ = nullptr;
};

class ConcreteDecoratorA: public Decorator
{
public:
    void Operation() override
    {
        Decorator::Operation();
        added_state_ = "New State";
        std::cout << "concrete decorator A" << std::endl;
    }
private:
    std::string added_state_;
};

class ConcreteDecoratorB:public Decorator
{
public:
    void Operation() override
    {
        Decorator::Operation();
        AddedBehavior();
        std::cout << "concrete decortator B" << std::endl;
    }
private:
    void AddedBehavior()
    {
        std::cout << "AddedBehavior"<< std::endl;
    }
};

int main()
{
    ConcreteComponent *p = new ConcreteComponent();
    ConcreteDecoratorA *d1 = new ConcreteDecoratorA();
    ConcreteDecoratorB *d2 = new ConcreteDecoratorB();
    d1->SetComponent(p);
    d1->Operation();

    d2->SetComponent(p);
    d2->Operation();

    delete d2;
    delete d1;
    delete p;

    return 0;
}

优点

  • a.比静态类更灵活

  • b.避免在层次结构高层的类有太多的特征

缺点

  • a.Decorator与它的Component不一样,Decorator只有一个透明的包装

  • b.当装饰的功能一多时,会有许多小对象

2.3 桥接模式 (Bridge)

特点

将抽象部分与它的实现部分分离,使它们都可以独立的变化。实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。

应用场景

  • a.不希望在抽象和它的实现部分之间有一个固定的绑定关系

  • b.类的抽象以及它的实现都应该可以通过生成子类的方法加以扩充

  • c.对一个抽象的实现部分的修改应对客户不产生影响

  • d.对客户完全隐藏抽象的实现部分

  • e.意图在多个对象间共享实现,但同时要求客户并不知道这一点

UML图

/images/design_pattern2_3.png

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/* 桥接模式 */
class Implementor
{
public:
    virtual void OperationImp() = 0;
};

class ConcreteImplementorA:public Implementor
{
public:
    void OperationImp() override
    {
        std::cout << "Concrete Implement A" << std::endl;
    }
};

class ConcreteImplementorB: public Implementor
{
public:
    void OperationImp() override
    {
        std::cout << "Concrete Implement B" << std::endl; 
    }
};

class Abstraction
{
public:
    void SetImplementor(Implementor *imp)
    {
        imp_  = imp;
    }
    virtual void Operation()
    {
        if(imp_ != nullptr)
        {
            imp_->OperationImp();
        }
    }
protected:
    Implementor *imp_ = nullptr;     
};

class RefinedAbstraction:public Abstraction
{
public:
    void Operation() override
    {
        Abstraction::Operation();
    }
};


int main()
{
    Abstraction *ab = new RefinedAbstraction();
    Implementor *p1 = new ConcreteImplementorA();
    Implementor *p2 = new ConcreteImplementorB();

    ab->SetImplementor(p1);
    ab->Operation();

    ab->SetImplementor(p2);
    ab->Operation();

    delete p2;
    delete p1;
    delete ab;

    return 0;
}

优点

  • a.分离接口及其实现部分

  • b.提高可扩充性

  • c.实现细节对客户透明

缺点: 无

2.4 组合模式 (Composite)

特点

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

应用场景

  • a.表达对象的部分-整体层次结构
  • b.希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象

UML图

/images/design_pattern2_4.png

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* 组合模式 */
class Component
{
public:
    Component(std::string name)
        :name_(name)
    {}
    virtual void Add(Component *component) = 0;
    virtual void Remove(Component *component) = 0;
    virtual void Display(int depth) = 0;
protected:
    std::string name_;
};

class Leaf:public Component
{
public:
    Leaf(std::string name)
        :Component(name)
    {}
    void Display(int depth) override
    {
        std::cout << "-" << depth << name_<< std::endl;
    }
    void Add(Component *) override
    {
    }
    void Remove(Component*) override
    {}
};

class Composite:public Component
{
public:
    Composite(std::string name )
        :Component(name)
    {}
    void Add(Component *component) override
    {
        children_.push_back(component);
    }
    void Remove(Component *component) override
    {
        for(auto it = children_.begin(); it != children_.end(); ++it)
        {
            if(*it == component)
            {
                children_.erase(it);
                break;
            }
        }
    }
    void Display(int depth)
    {
        std::cout << "-" << depth << name_ << std::endl;
        for(auto it : children_)
        {
            it->Display(depth + 1);
        }
    }
private:
    std::vector<Component*> children_;
};

int main()
{
    Composite *root = new Composite("root");
    root->Add(new Leaf("Leaf A"));
    root->Add(new Leaf("Leaf B"));

    Composite *comp = new Composite("Composite X");
    comp->Add(new Leaf("Leaf XA"));
    comp->Add(new Leaf("Leaf XB"));

    root->Add(comp);

    Composite *comp2 = new Composite("Composite XY");
    comp2->Add(new Leaf("Leaf XYA"));
    comp2->Add(new Leaf("Leaf XYB"));
    comp->Add(comp2);

    root->Add(new Leaf("Leaf C"));
    Leaf *leaf = new Leaf("Leaf D");
    root->Add(leaf);
    root->Remove(leaf);

    root->Display(1);

    return 0;
}

优点

  • a.定义了包含基本对象和组合对象的层次结构

  • b.简化客户代码

  • c.使得更容易增加新类型的组件

  • d.是设计变得更加一般化

缺点: 无

2.5 享元模式 (Flyweight)

特点

运用共享技术有效的支持大量细粒度的对象。享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来标识数据。如果能发现这些实例除了几个参数外基本上都是相同的,有时就能大幅度地减少需要实例化的类的数量。如果能把那些参数移到类实例的外面,在方法调用时将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

应用场景

一个应用程序使用了大量的对象,并且大量的对象造成巨大的开销,对象的大多数状态对可变为外部状态,可使用相对较少的共享对象取代很多组对象,不依赖于对象标识,此时可考虑使用享元模式

UML图

/images/design_pattern2_5.png

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/* 享元模式 */
class FlyWeight
{
public:
    virtual void Operation(int extra_state) = 0;
};

class ConcreteFlyWeight:public FlyWeight
{
public:
    void Operation(int extra_state) override
    {
        std::cout << "Concrete FlyWeight " << extra_state << std::endl;
    }
};

class UnsharedConcreteFlyWeight:public FlyWeight
{
public:
    void Operation(int extra_state) override
    {
        std::cout << "Unshared Concrete FlyWeight " << extra_state << std::endl;
    }
};

class FlyWeightFactory
{
public:
    FlyWeightFactory()
    {
        fly_weights_.emplace("X",new ConcreteFlyWeight());
        fly_weights_.emplace("Y",new ConcreteFlyWeight());
        fly_weights_.emplace("Z",new ConcreteFlyWeight());
    }
    ~FlyWeightFactory()
    {
        for(auto it = fly_weights_.begin(); it != fly_weights_.end();)
        {
            delete it->second;
            it = fly_weights_.erase(it);
        }
    }
    FlyWeight* GetFlyWeight(std::string key)
    {
        return fly_weights_[key];
    }
private:
    std::map<std::string,FlyWeight*> fly_weights_;
};

int main()
{
    int extra_state = 22;

    FlyWeightFactory *f = new FlyWeightFactory();

    FlyWeight *fx = f->GetFlyWeight("X");
    fx->Operation(--extra_state);

    FlyWeight *fy = f->GetFlyWeight("Y");
    fy->Operation(--extra_state);

    FlyWeight *fz = f->GetFlyWeight("Z");
    fz->Operation(--extra_state);

    UnsharedConcreteFlyWeight *uf = new UnsharedConcreteFlyWeight();
    uf->Operation(--extra_state);

    return 0;
}

优点: 节约存储

缺点

  • a. 对象太多时,会造成运行时的资源与性能损耗
  • b.为了使对象共享需要将一些状态外部化,使得程序的逻辑复杂化

2.6 代理模式(Proxy)

特点

为其他对象提供一种代理以控制对这个对象的访问。

应用场景

  • a.远程代理 为一个对象在不同的地址空间提供局部代表
  • b.虚代理 根据需要创建开销很大的对象
  • c.保护代理 控制原始对象的访问
  • d.智能指引 取代了简单的指针,它在访问对象时执行一些附加的操作

UML图

/images/design_pattern2_6.png

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/* 代理模式 */
class Subject
{
public:
    virtual void Request() = 0;
};
class RealSubject: public Subject
{
 public:
    void Request() override
    {
        std::cout << "Real Request" << std::endl;
    }
};

class Proxy: public Subject
{
public:
    Proxy() = default;
    ~Proxy()
    {
        if(real_subject_ != nullptr)
        {
            delete real_subject_;
        }
    }
    void Request() override
    {
        if(real_subject_ == nullptr)
        {
            real_subject_ = new RealSubject();
        }
        real_subject_->Request();
    }
private:
    Subject *real_subject_;
};

int main()
{
    Proxy *proxy = new Proxy();
    proxy->Request();


    delete proxy;

    return 0;
}

优点

  • a.远程代理可以隐藏一个对象存在于不同地址空间的事实
  • b.虚代理可以进行最优化,例如根据要求创建对象
  • c.保护代理和只能指引对允许在访问一个对象时有一些附加的内务处理

缺点: 无

2.7 外观模式(Facade)

特点: 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,使得这一子系统更加容易使用

应用场景

  • a.当需要为一个复杂的子系统提供一个简单接口时
  • b.客户程序

UML图

/images/design_pattern2_7.png

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/* 外观模式 */
class SubSystemOne
{
public:
    void MethodOne()
    {
        std::cout << "Subsystem Function one" << std::endl;
    }
};

class SubSystemTwo
{
public:
    void MethodTwo()
    {
        std::cout << "Subsystem Function two" << std::endl;
    }
};

class SubSystemThree
{
public:
    void MethodThree()
    {
        std::cout << "Subsystem Function three" << std::endl;
    }
};

class SubSystemFour
{
public:
    void MethodFour()
    {
        std::cout << "Subsystem Function four" << std::endl;
    }
};

class Facade
{
public:
    Facade()
    {
        one_ = new SubSystemOne();
        two_ = new SubSystemTwo();
        three_ = new SubSystemThree();
        four_ = new SubSystemFour();
    }
    ~Facade()
    {
        delete one_;
        delete two_;
        delete three_;
        delete four_;
    }

    void MethodA()
    {
        std::cout << "Group A" << std::endl;
        one_->MethodOne();
        two_->MethodTwo();
        four_->MethodFour();
    }

    void MethodB()
    {
        std::cout << "Group B" << std::endl;
        two_->MethodTwo();
        three_->MethodThree();
    }

private:
    SubSystemOne *one_;
    SubSystemTwo *two_;
    SubSystemThree *three_;
    SubSystemFour *four_;
};

int main()
{
    Facade *facade = new Facade();
    facade->MethodA();
    facade->MethodB();
    
    delete facade;

    return 0;
}

优点

  • a.对客户屏蔽了子系统组件
  • b.实现了子系统与客户之间的松耦合关系
  • c.不限制使用子系统类

缺点

需要在系统的通用性和易用性之间做取舍