设计模式——工厂方法

2023-08-12  本文已影响0人  东方胖

设计模式是指在使用静态语言(动态脚本语言也适用,但是由于存在较大的语言差异,把静态语言的编码方法“翻译”到动态语言中,往往会破坏一些编码原则,以后可能会专门辟一文来对比C++和Python)
中针对某些问题的一种编码模式,

具体而言,一个模式可能是一组类之间的关系的“拼凑”——协作关系。

在学习设计模式时,一般需要弄清楚上述的所谓协作关系。

因为必须要知道所谓的 OO —— Object-Orient 编程——面向对象编程

本文不述

先陈列几种在面向对象语言下的代码协作关系

class B;
class A {
public:
    A() {
    }

private:
   B * b;
};

上面的组合,意味着 B在其域内——任何函数内部,可以用 b的句柄,操纵 A 的方法(A中那些声明为 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.
以上的定义中,可以看到
工厂模式主要有两个特性:

第二点颇难索解,原因在于上面那个用枚举类型分拆的写法没有定义纯接口,直接在第一层的创建函数中就开始实现。实际上可以在子类中来做,并且把 switch-case的写法也可以改成一个一个的抽象接口的样子。

于是,凡我们见到创建对象不是用 new 而是要调一个接口 createXXX 或者buildXXX我们知道 多半是运用了工厂模式。

工厂方法的几个变种

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 然后增加接口进行创建新类型。

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;// 

上面这种模版方法很广泛存在各种类库,稍加注意

上一篇 下一篇

猜你喜欢

热点阅读