设计模式是指在使用静态语言(动态脚本语言也适用,但是由于存在较大的语言差异,把静态语言的编码方法“翻译”到动态语言中,往往会破坏一些编码原则,以后可能会专门辟一文来对比C++和Python)
中针对某些问题的一种编码模式,
具体而言,一个模式可能是一组类之间的关系的“拼凑”——协作关系。
在学习设计模式时,一般需要弄清楚上述的所谓协作关系。
因为必须要知道所谓的 OO —— Object-Orient 编程——面向对象编程
本文不述
先陈列几种在面向对象语言下的代码协作关系
- association
通常是指 类A中的某个函数的参数是类型是 B ,于是 A 和 B就有一种联系,这种关系比较弱 - 组合
类B 作为子成员置于B的属性中,A持有B的句柄,引用,或者说指针。
例子
class B;
class A {
public:
A() {
}
private:
B * b;
};
上面的组合,意味着 B在其域内——任何函数内部,可以用 b的句柄,操纵 A 的方法(A中那些声明为 public的方法)
- 聚合
作为一种1-n的组合方式 - 继承
继承是作为面向对象比较特别的东西,当一个类B 从另一个类A继承时,B一般叫子类,A 一般叫父类,子类继承父类,会把protected 的属性和方法复制过来,当然,作为子类,对父类的“隐私”也是具有一定窥视权,窥视的范围有多大取决于继承的方式
有三种 public private protect
最常见的 是 public 继承。
另一种继承利用的时面对象语言最重要的一个特性:多态
多态使得子类可以从父类继承一种命名保持一致性的函数方法,然后在运行时决定到底是运行哪个子类的方法。
在几乎所有的所谓设计模式中,多态特性几乎都会亮相
以上常见的协作,构成了设计模式实现中的基本成分
工厂方法
以前我印象中工厂方法是大概这样的样子:
class Product
{
};
class ProductA: public Product
{
};
class ProductB: public Product
{
};
class Factory
{
public:
enum ProductType
{
A = 0,
B = 1
};
virtual Product* createProduct(int type) {
switch (type) {
case A:
return new ProcuctA();
case B:
return new ProductB();
default:
// ...
}
}
Factory 定义了一个抽象的方法,如果需要扩展产品C ProductC ,那么需要继承 Factory(在Facotory 中改也可以,但是导致要覆盖测试所有之前的代码,需要改动几个地方)
扩展 createProduct方法可以修改逻辑,如下
Product* createProduct(int type) {
switch (type) {
case C:
return new ProcuctC();
}
return Factory::createProduct(type);
}
用工厂模式,最大的特点是什么。其实是那new ProductXXX 隐藏起来。
我们正常的编码方式是像下面这样
ProductA * a = new ProductA();
出现在某处上下文中。
这种办法其实没什么问题,只是在当 ProductA ProductC ProductB变成一个系列的时候,并且,随时会ABC发生一些替换的修改发生,这样我们需要改 new ProductA()的代码
看看《设计模式-可复用面向对象的基础》这本书怎么描述工厂模式的。
Define a interface for creating an object , but let subclasses decide which class to instancitate.Factory Method lets a class defer instantiation to subclasses.
以上的定义中,可以看到
工厂模式主要有两个特性:
- 定义接口创建对象。即上面说得 把new ProductXXX这种代码隐藏起来
- 子类决定实例化哪个类。 工厂模式将类的实例化延迟到子类中。
第二点颇难索解,原因在于上面那个用枚举类型分拆的写法没有定义纯接口,直接在第一层的创建函数中就开始实现。实际上可以在子类中来做,并且把 switch-case的写法也可以改成一个一个的抽象接口的样子。
于是,凡我们见到创建对象不是用 new 而是要调一个接口 createXXX 或者buildXXX我们知道 多半是运用了工厂模式。
工厂方法的几个变种
- 除了上面的参数化的写法,还有一种是每个类型的Product对应一个工厂方法
类似下面的代码—从《设计模式》这本书中摘取
class MazeGame
{
Maze* CreateMaze() ;
// factory
virtual Maze* MakeMaze() const {return new Maze();}
virtual Room* MakeRoom() const {return new Room();}
virtual Wall *MakeWall() const {return new Wall();}
virtual Door* MakeDoor() const {return new Door(); }
}
以上的 virtual 接口都是工厂方法
如果有新的组件需要扩展,则继承 MazeGame 然后增加接口进行创建新类型。
- 一种模版方法可以省掉每次有新品要创建就得创建MazeGame子类的方法
概要如下
class Creator
{
public:
virtual createProduct() = 0;
} ;
template<class TheProduct>
class MazeGame: public Creator {
virtual Product* createProduct();
};
class MyProduct: public Product
{
public:
};
// client code
MazeGame<MyProduct> myCreator;//
上面这种模版方法很广泛存在各种类库,稍加注意
网友评论