桥接模式及C++实现 C++设计模式-AbstractFactory抽象工厂模式
桥接模式及C++实现
桥接模式
先说说桥接模式的定义:将抽象化(Abstraction)与实现化(Implementation)分离,使得二者可以独立地变化。
桥接模式号称设计模式中最难理解的模式之一,关键就是这个抽象和实现的分离非常让人奇怪,大部分人刚看到这个定义的时候都会认为实现就是继承自抽象,那怎么可能将他们分离呢。
这里引用《大话设计模式》里面的那个例子。这个例子中,每次添加一个新的手机品牌,则必须要添加相应的通讯录和游戏,而每次要给每个手机添加新功能,则所有的手机品牌下都必须继承一个新的类,这样工作量就大了,而且可能通讯录和游戏的实现方法是一样的,这就有很多重复代码。看到这里可能已经看到了端倪了,虽然这个最顶层的抽象手机品牌一般是固定不变的,但是下面的各个继承类手机品牌M和手机品牌N却是时常会发生变化的。而只要手机品牌M和手机品牌N发生变化,它下面的继承类也要发生变化,这样极大的增加了代码的耦合性,加入通讯录和游戏下面还继续继承有类的话,那耦合性就更强了,改起来基本就是噩梦了。
其实也可以这样看,虽然手机品牌M和手机品牌N这两个类是有一部分抽象,但是还没有达到完全的抽象,还是会发生变化的。
所以,其实定义里说的实现是指的最下层的那些具体实现,抽象是指的他的父类或者更上层的父类,而要将抽象和实现分离,就是分离这个抽象和实现。说的通俗点,就是不要继承的太多了,最好是就继承一层。(我自己的理解)所以才有了合成/聚合复用原则。
合成/聚合复用原则:尽量使用合成/聚合,尽量不要使用类继承。我对这句话的理解就是,不要继承太多了,如果需要太多继承,可以考虑改为合成/聚合。
下面可以看看桥接模式的具体类图了。桥接模式就将实现与抽象分离开来,使得RefinedAbstraction依赖于抽象的实现,这样实现了依赖倒转原则,而不管左边的抽象如何变化,只要实现方法不变,右边的具体实现就不需要修改,而右边的具体实现方法发生变化,只要接口不变,左边的抽象也不需要修改。
说起来,其实桥接模式倒是与抽象工厂模式有点像,可以回忆一下抽象工厂模式,抽象工厂模式也是解决多种因素变化的一种方式,抽象工厂模式中,产品的种类和产品的具体实现都会发生变化,于是将产品的种类抽象出来,将具体的实现隔离开来。
常用的场景
1.当一个对象有多个变化因素的时候,考虑依赖于抽象的实现,而不是具体的实现。如上面例子中手机品牌有2种变化因素,一个是品牌,一个是功能。
2.当多个变化因素在多个对象间共享时,考虑将这部分变化的部分抽象出来再聚合/合成进来,如上面例子中的通讯录和游戏,其实是可以共享的。
3.当我们考虑一个对象的多个变化因素可以动态变化的时候,考虑使用桥接模式,如上面例子中的手机品牌是变化的,手机的功能也是变化的,所以将他们分离出来,独立的变化。
优点
1.将实现抽离出来,再实现抽象,使得对象的具体实现依赖于抽象,满足了依赖倒转原则。
2.将可以共享的变化部分,抽离出来,减少了代码的重复信息。
3.对象的具体实现可以更加灵活,可以满足多个因素变化的要求。
缺点
1.客户必须知道选择哪一种类型的实现。
C++实现代码
1 #ifndef _ABSTRACTION_H_
2 #define _ABSTRACTION_H_
3
4 #include "AbstractionImplement.h"
5
6 class Abstraction
7 {
8 public:
9 Abstraction();
10 virtual ~Abstraction();
11
12 virtual void operation() = 0;
13
14
15 };
16
17 class DefinedAbstraction: public Abstraction
18 {
19 public:
20 DefinedAbstraction(AbstractionImplement* absImp);
21 ~DefinedAbstraction();
22
23 void operation();
24
25 private:
26 AbstractionImplement* absImp;
27 };
28
29
30 #endif
1 #include "Abstraction.h"
2
3
4 Abstraction::Abstraction()
5 {
6
7 }
8
9
10
11 Abstraction::~Abstraction()
12 {
13
14 }
15
16
17 DefinedAbstraction::DefinedAbstraction(AbstractionImplement* absImp)
18 {
19 this->absImp = absImp;
20 }
21
22
23 DefinedAbstraction::~DefinedAbstraction()
24 {
25
26 }
27
28
29 void DefinedAbstraction::operation()
30 {
31 absImp->operation();
32 }
1 #ifndef _ABSTRACTIONIMPLEMENT_H_
2 #define _ABSTRACTIONIMPLEMENT_H_
3
4
5 class AbstractionImplement
6 {
7 public:
8 AbstractionImplement();
9 virtual ~AbstractionImplement();
10
11 virtual void operation() = 0;
12 };
13
14
15 class ConcreteAbstractionImplement1:public AbstractionImplement
16 {
17 public:
18 ConcreteAbstractionImplement1();
19 ~ConcreteAbstractionImplement1();
20
21 void operation();
22 };
23
24 class ConcreteAbstractionImplement2:public AbstractionImplement
25 {
26 public:
27 ConcreteAbstractionImplement2();
28 ~ConcreteAbstractionImplement2();
29
30 void operation();
31 };
32
33
34 #endif
1 #include "AbstractionImplement.h"
2 #include <stdio.h>
3
4
5
6 AbstractionImplement::AbstractionImplement()
7 {
8
9 }
10
11
12 AbstractionImplement::~AbstractionImplement()
13 {
14
15 }
16
17
18 ConcreteAbstractionImplement1::ConcreteAbstractionImplement1()
19 {
20
21 }
22
23
24 ConcreteAbstractionImplement1::~ConcreteAbstractionImplement1()
25 {
26
27 }
28
29
30 void ConcreteAbstractionImplement1::operation()
31 {
32 fprintf(stderr, "ConcreteAbstractionImplement1\n" );
33 }
34
35
36 ConcreteAbstractionImplement2::ConcreteAbstractionImplement2()
37 {
38
39 }
40
41
42 ConcreteAbstractionImplement2::~ConcreteAbstractionImplement2()
43 {
44
45 }
46
47
48 void ConcreteAbstractionImplement2::operation()
49 {
50 fprintf(stderr, "ConcreteAbstractionImplement2\n" );
51 }
1 #include "Abstraction.h"
2
3
4
5 int main()
6 {
7 AbstractionImplement* absImp1 = new ConcreteAbstractionImplement1();
8 Abstraction* abs1 = new DefinedAbstraction(absImp1);
9
10 abs1->operation();
11
12 AbstractionImplement* absImp2 = new ConcreteAbstractionImplement2();
13 Abstraction* abs2 = new DefinedAbstraction(absImp2);
14
15 abs2->operation();
16 return 0;
17 }
1 g++ -o client client.cpp Abstraction.cpp AbstractionImplement.cpp
运行结果
AbstractFactory
要创建一组相关或者相互依赖的对象
作用:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
UML结构图:
抽象基类:
1)AbstractProductA、AbstractProductB:分别代表两种不同类型的产品,由具体的产品派生类对其实现
2)AbstractFactory:抽象工厂类,提供创建两种产品的接口CreateProductA和CreateProductB,由派生的各个具体工厂类对其实现
说明:
AbstractFactory模式关键就是将这一组对象的创建封装到一个用于创建对象的类(ConcreteFactory)中
Abstract Factory模式和Factory最大的差别就是抽象工厂创建的是一系列相关的对象,其中创建的实现其实采用的就是Factory模式的方法,对于某个实现的有一个派生出来的抽象工厂,另一个实现有另一个派生出来的工厂
抽象工厂需要特别注意的地方就是区分不同类型的产品和这些产品的不同实现.显而易见的,如果有n种产品同时有m中不同的实现,那么根据乘法原理可知有n*m个Factory模式的使用
AbstractFactory模式是为创建一组(有多类)相关或依赖的对象提供创建接口,而Factory模式是为一类对象提供创建接口或延迟对象的创建到子类中实现。并且可以看到,AbstractFactory模式通常都是使用Factory模式实现(ConcreteFactory1)。
代码如下:
Product.h
1 #ifndef _PRODUCT_H_
2 #define _PRODUCT_H_
3
4 //抽象基类AbstractProductA,代表A类产品的抽象
5 class AbstractProductA
6 {
7 public:
8 virtual ~AbstractProductA()=0;
9 virtual void operation()=0;
10 protected:
11 AbstractProductA();//屏蔽构造函数
12 };
13
14 //派生类ProductA1,继承自AbstractProductA,A类产品的一种实现
15 class ProductA1 : public AbstractProductA
16 {
17 public:
18 ProductA1();
19 virtual void operation();
20 virtual ~ProductA1();
21 };
22
23 //派生类ProductA2,继承自AbstractProductA,A类产品的另一种实现
24 class ProductA2:public AbstractProductA
25 {
26 public:
27 ProductA2();
28 virtual void operation();
29 virtual ~ProductA2();
30 };
31
32 //抽象基类AbstractProductB,代表B类产品的抽象
33 class AbstractProductB
34 {
35 public:
36 virtual ~AbstractProductB()=0;
37 virtual void operation()=0;
38 protected:
39 AbstractProductB();//屏蔽构造函数
40 };
41
42 //派生类ProductB1,继承自AbstractProductB,B类产品的一种实现
43 class ProductB1:public AbstractProductB
44 {
45 public:
46 ProductB1();
47 virtual void operation();
48 virtual ~ProductB1();
49 };
50
51 //派生类ProductB2,继承自AbstractProductB,B类产品的另一种实现
52 class ProductB2:public AbstractProductB
53 {
54 public:
55 ProductB2();
56 virtual void operation();
57 virtual ~ProductB2();
58 };
59
60
61 #endif
Factory.h
1 #ifndef _FACTORY_H_
2 #define _FACTORY_H_
3
4 //AbstractFactory,工厂抽象基类,定义生产A类与B类产品的接口
5 class AbstractProductA;
6 class AbstractProductB;
7 class AbstractFactory
8 {
9 public:
10 virtual ~AbstractFactory()=0;
11 virtual AbstractProductA* CreateProductA()=0;
12 virtual AbstractProductB* CreateProductB()=0;
13 protected:
14 AbstractFactory();
15 };
16
17 //ConcreteFactory1,派生类,继承自AbstractFactory
18 //实现继承的接口,生产产品A和B的一种实现
19 class ConcreteFactory1:public AbstractFactory
20 {
21 public:
22 ConcreteFactory1();
23 ~ConcreteFactory1();
24 virtual AbstractProductA* CreateProductA();
25 virtual AbstractProductB* CreateProductB();
26 };
27
28 //ConcreteFactory2,派生类,继承自AbstractFactory
29 //实现继承的接口,生产产品A和B的另一种实现
30 class ConcreteFactory2:public AbstractFactory
31 {
32 public:
33 ConcreteFactory2();
34 ~ConcreteFactory2();
35 virtual AbstractProductA* CreateProductA();
36 virtual AbstractProductB* CreateProductB();
37 };
38
39 #endif
Product.cpp
1 #include "Product.h"
2 #include <iostream>
3
4 using namespace std;
5
6 //AbstractProductA
7 AbstractProductA::AbstractProductA()
8 {
9 cout << "AbstractProductA..." << endl;
10 }
11
12 AbstractProductA::~AbstractProductA()
13 {
14 cout << "~AbstractProductA..." << endl;
15 }
16
17 //ProductA1
18 ProductA1::ProductA1()
19 {
20 cout << "ProductA1..." << endl;
21 }
22
23 ProductA1::~ProductA1()
24 {
25 cout << "~ProductA1..." << endl;
26 }
27
28 void ProductA1::operation()
29 {}
30
31 //ProductA2
32 ProductA2::ProductA2()
33 {
34 cout << "ProductA2..." << endl;
35 }
36
37 ProductA2::~ProductA2()
38 {
39 cout << "~ProductA2..." << endl;
40 }
41
42 void ProductA2::operation()
43 {}
44
45 //AbstractProductB
46 AbstractProductB::AbstractProductB()
47 {
48 cout << "AbstractProductB..." << endl;
49 }
50
51 AbstractProductB::~AbstractProductB()
52 {
53 cout << "~AbstractProductB..." << endl;
54 }
55
56 //ProductB1
57 ProductB1::ProductB1()
58 {
59 cout << "ProductB1..." << endl;
60 }
61
62 ProductB1::~ProductB1()
63 {
64 cout << "~ProductB1..." << endl;
65 }
66
67 void ProductB1::operation()
68 {}
69
70 //ProductB2
71 ProductB2::ProductB2()
72 {
73 cout << "ProductB2..." << endl;
74 }
75
76 ProductB2::~ProductB2()
77 {
78 cout << "~ProductB2..." << endl;
79 }
80
81 void ProductB2::operation()
82 {}
Factory.cpp
1 #include "Factory.h"
2 #include "Product.h"
3 #include <iostream>
4
5 using namespace std;
6
7 AbstractFactory::AbstractFactory()
8 {
9 cout << "AbstractFactory..." << endl;
10 }
11
12 AbstractFactory::~AbstractFactory()
13 {
14 cout << "~AbstractFactory..." << endl;
15 }
16
17 ConcreteFactory1::ConcreteFactory1()
18 {
19 cout << "ConcreteFactory1..." << endl;
20 }
21
22 ConcreteFactory1::~ConcreteFactory1()
23 {
24 cout << "~ConcreteFactory1..." << endl;
25 }
26
27 AbstractProductA* ConcreteFactory1::CreateProductA()
28 {
29 return new ProductA1();
30 }
31
32 AbstractProductB* ConcreteFactory1::CreateProductB()
33 {
34 return new ProductB1();
35 }
36
37 ConcreteFactory2::ConcreteFactory2()
38 {
39 cout << "ConcreteFactory2..." << endl;
40 }
41
42 ConcreteFactory2::~ConcreteFactory2()
43 {
44 cout << "~ConcreteFactory2..." << endl;
45 }
46
47 AbstractProductA* ConcreteFactory2::CreateProductA()
48 {
49 return new ProductA2();
50 }
51
52 AbstractProductB* ConcreteFactory2::CreateProductB()
53 {
54 return new ProductB2();
55 }
main.cpp
1 #include <iostream>
2 #include "Factory.h"
3 #include "Product.h"
4
5 using namespace std;
6
7 int main()
8 {
9 AbstractFactory* fa1 = new ConcreteFactory1();
10 AbstractProductA* a1 = fa1->CreateProductA();
11 AbstractProductB* b1 = fa1->CreateProductB();
12
13 cout << endl;
14 AbstractFactory* fa2 = new ConcreteFactory2();
15 AbstractProductA* a2 = fa2->CreateProductA();
16 AbstractProductB* b2 = fa2->CreateProductB();
17
18 cout << endl;
19 delete fa1;
20 delete a1;
21 delete b1;
22
23 cout << endl;
24 delete fa2;
25 delete a2;
26 delete b2;
27
28 return 0;
29 }
桥接模式及C++实现 C++设计模式-AbstractFactory抽象工厂模式的更多相关文章
- C++设计模式-AbstractFactory抽象工厂模式
AbstractFactory 要创建一组相关或者相互依赖的对象 作用:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. UML结构图: 抽象基类: 1)AbstractProdu ...
- C#设计模式之四抽象工厂模式(AbstractFactory)【创建型】
一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了 ...
- C#设计模式之三抽象工厂模式(AbstractFactory)【创建型】
一.引言 写了3篇有关设计模式的文章了,大家有了些反馈,说能从中学到一些东西,我感到很欣慰,那就继续努力.今天我要写第四个模式了,该模式叫抽象工厂.上一篇文章我们讲了[工厂方法]模式,它是为了解决[简 ...
- 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern)
原文:乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factory Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 抽象工厂模式(Abstract Factor ...
- 再起航,我的学习笔记之JavaScript设计模式06(抽象工厂模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...
- 【设计模式】抽象工厂模式 Abstract Factory Pattern
简单工厂模式是一个工厂类根据工厂方法的参数创建不出不同的产品, 工厂方法模式是每一个产品都有一个一一对应的工厂负责创建该产品.那么今天要讲的抽象工厂模式是一个工厂能够产生关联的一系列产品.抽象工厂模式 ...
- 再起航,我的学习笔记之JavaScript设计模式07(抽象工厂模式)
我的学习笔记是根据我的学习情况来定期更新的,预计2-3天更新一章,主要是给大家分享一下,我所学到的知识,如果有什么错误请在评论中指点出来,我一定虚心接受,那么废话不多说开始我们今天的学习分享吧! 前两 ...
- 设计模式之抽象工厂模式(Abstract Factory Pattern)
一.抽象工厂模式的由来 抽象工厂模式,最开始是为了解决操作系统按钮和窗体风格,而产生的一种设计模式.例如:在windows系统中,我们要用windows设定的按钮和窗体,当我们切换Linux系统时,要 ...
- Java 设计模式之抽象工厂模式(三)
原文地址:Java 设计模式之抽象工厂模式(三) 博客地址:http://www.extlight.com 一.前言 上篇文章 <Java 设计模式之工厂模式(二)>,介绍了简单工厂模式和 ...
随机推荐
- HDU 4228 Flooring Tiles 反素数
推出了结论,万万没想到最后用搜索.. 还想dp来着.. #include <cstdio> #include <cstring> #include <iostream&g ...
- Caused by: java.lang.ClassNotFoundException: org.dom4j.DocumentException
1.错误描写叙述 信息: Initializing c3p0-0.9.2.1 [built 20-March-2013 10:47:27 +0000; debug? true; trace: 10] ...
- Windows 7硬盘安装CentOS 6.4 双系统 (WIN7硬盘安装Linux(Fedora 16,CentOS 6.2,Ubuntu 12.04))
WIN7下硬盘安装Linux(Fedora 16,CentOS 6.2.Ubuntu 12.04) 近期在看<鸟哥私房菜:基础学习篇>.认为非常不错,想要用U盘装个windows 7 和 ...
- Javascript实战开发:教你使用raphael.js绘制中国地图
最近的数据统计项目中要用到中国地图,也就是在地图上动态的显示某个时间段某个省份地区的统计数据,我们不需要flash,仅仅依靠raphael.js以及SVG图像就可以完成地图的交互操作.在本文中,我给大 ...
- html5 图片上传版本1.0
1.代码如下: /* autor:shzihouyu date:2015-12-11 ver:1.0 */ var szyFile = { fileDom:null,//html 文件上传控件 pre ...
- Dev环境中的集成测试用例执行时上下文环境检查(实战)
Dev环境中的集成测试用例执行时上下文环境检查(实战) Microsoft.NET 解决方案,项目开发必知必会. 从这篇文章开始我将分享一系列我认为在实际工作中很有必要的一些.NET项目开发的核心技术 ...
- 如何配置Spring的XML文件及使用
App.config <?xml version="1.0" encoding="utf-8" ?> <configuration> & ...
- ps入门教程:画笔工具、铅笔工具、渐变工具等的使用
本节课程主要内容:学习画笔工具.铅笔工具.颜色替换工具.历史记录画笔工具.历史记录艺术画笔工具.渐变工具和油漆桶 工具的应用.------------------------------------- ...
- Visual Studio 当前不会命中断点的问题
这个问题一般有两个版本 1.当前不会命中断点,还没有为该文档加载任何符号. 2.当前不会命中断点,源代码与原始版本不同. 要解决第一个问题,就要了解一种文件格式“PDB(Program DataBas ...
- cefsharp实现javascript回调C#方法
在构建完WebView webView = new WebView(url)后,即可调用RegisterJsObject方法来注册一个js对象,从而前端的javascript就可以访问这个对象,调用定 ...