## 简述
### 工厂模式分三种类型。
        1. 简单工厂模式。
        2. 工厂方法模式。
        3. 抽象工厂模式。

## 设计的原则和思想
1. 解耦了对象的创建和使用。
2. 不变部分是使用，变化部分是创建。
3. 核心思想是对象的创建封装在工厂类中。

### 产品等级结构和产品族
    产品等级结构 : 
        继承结构，就是同类。例如，华为手机，小米手机，魅族手机，这些都是具体实现类，抽象类是手机。  

    产品族 : 
        是同一个牌子的产品,都是由同一个工厂生产的。例如，华为手机，华为平板，华为电脑，这些构成了一个华为的产品族。


## 简单工厂模式 - Simple Factory Pattern

### 定义
   1. 一个工厂类，根据参数的不同返回不同类的实例。
   2. 简单工厂模式中用于创建实例的方法是静态(static)方法，因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式。


### 一句话概括设计模式
    一个静态方法返回产品对象。


### 结构中包含的角色
    1. Factory（工厂角色）
    2. Product（抽象产品角色）
    3. ConcreteProduct（具体产品角色）

### 最小可表达代码
    // 产品
    abstract class Product {}
    class ConcreteProductA extends Product {}
    class ConcreteProductOther extends Product {}

    // 简单工厂
    class SimpleFactory {
        public static getProduct($param) : Product
        {  
            if ("A" == $param) {
                return new ConcreteProductA();  
            }  

            return new ConcreteProductOther();
        }  
    }

### 优点
1. 根据参数就可以创建产品，不需要知道产品的具体实现。
2. 实现对象的创建和使用分离。

### 缺点
1. 随着时间的推移，产品的具体类逐渐增多，工厂的逻辑会逐渐复杂，不利于系统的扩展和维护。
2. 增加产品等级结构，需要增加对应的工厂类，增加产品族也必须修改工厂类。

### 何时使用
1. 根据不同的条件生成不同的对象，并且创建的对象比较少，例如框架中配置的驱动。
2. 一个对象的创建比较复杂。

### 实际应用场景
1. PDO中的数据库驱动。Mysql，DB2，还是Oracle。




## 工厂方法模式 - Factory Method Pattern

### 定义
1. 一个用于创建对象的接口，让子类决定将哪一个类实例化(一个工厂实例化一个产品类)。
2. 工厂方法模式又简称为工厂模式(Factory Pattern)，又可称作虚拟构造器模式(Virtual Constructor Pattern)或多态工厂模式(Polymorphic Factory Pattern)。


### 一句话概括设计模式
	不同的工厂返回不同的产品对象。


### 结构中包含的角色
1. Product（抽象产品）
2. ConcreteProduct（具体产品）
3. Factory（抽象工厂）
4. ConcreteFactory（具体工厂）


### 最小可表达代码
    // 产品
    interface Product {}
    class ConcreteProductA implements Product {}
    class ConcreteProductOther implements Product {}

    // 工厂
    interface Factory {
        public function createProduct() : Product;
    }
    class ConcreteFactoryA implements Factory {  
        public public createProduct() : Product
        {  
            return new ConcreteProductA();
        }     
    }
    class ConcreteFactoryOther implements Factory {  
        public public createProduct() : Product
        {  
            return new ConcreteProductOther();
        }     
    }

### 优点
1. 客户端只要知道产品对应的工厂即可，不需要知道具体产品的类名。
2. 新增产品只需要添加一个具体工厂和具体产品就可以了，可扩展性非常好。

### 缺点
1. 新增产品会导致系统中存在大量的工厂类。
2. 使用了抽象，并且实现时可能还会用到反射或者IOC，增加了系统的复杂度。

### 何时使用
1. 工厂方法模式实际上是多个简单工厂模式的集合。所以，当简单工厂里面的产品过多时，可以使用工厂方法模式解耦。
2. 运行时动态决定所需的类。可将具体工厂类的类名存储在配置文件，运行时通过反射实例化。虽然简单工厂也可以做到，但是违反了开闭原则。

### 实际应用场景
1. 商城的商品有精选商品，收藏的商品，销售最高的商品，每类商品都有所差异，可以使用工厂方法模式设计。
2. 框架中，通过配置实例化类。例如laravel中，通过config/cache配置选择缓存（redis 或 memcached）驱动。





## 抽象工厂模式-Abstract Factory Pattern

### 定义
    提供一个创建一系列相关或相互依赖对象的接口（每个工厂负责创建整个产品族），而无须指定它们具体的类。


### 一句话概括设计模式
	一个工厂有不同的方法，不同的方法返回不同的产品对象。简单就是一个工厂返回一系列产品。



### 结构中包含的角色
1. AbstractFactory（抽象工厂）
2. ConcreteFactory（具体工厂）
3. AbstractProduct（抽象产品）
4. ConcreteProduct（具体产品）

### 最小可表达代码
    // 手机产品
    interface Phone {}  
    class HuaWeiPhone implements Phone {}   
    class XiaoMiPhone implements Phone {}  

    // 笔记本产品
    interface NoteBook {}  
    class HuaWeiNoteBook implements NoteBook {}   
    class XiaoMiNoteBook implements NoteBook {}  

    // 工厂
    interface Factory {  
        public function createPhone() : Phone;  
        public function createNoteBook() : NoteBook; 
    }  
    // 华为工厂
    class HuaWeiFactory implements Factory {  
        public function createPhone() {  
            return new HuaWeiPhone();  
        }  
        public function createNoteBook() {  
            return new HuaWeiNoteBook();  
        }
    } 
    // 小米工厂
    class XiaoMiFactory implements Factory {  
        public function createPhone()
        {  
            return new XiaoMiPhone();  
        }  
        public function createNoteBook() {  
            return new XiaoMiNoteBook();  
        }  
    }

### 优点
1. 增加新的产品族（新增具体工厂和具体产品）无须修改已有系统，符合开闭原则。

### 缺点
1. 增加新的产品等级结构（所有具体工厂都要修改，新增抽象产品和具体产品），需要对原有系统进行较大的修改。

### 何时使用
1. 抽象工厂模式实际上是多个工厂方法模式的集合。所以，当工厂方法模式里面存在多个产品等级结构时，可以使用抽象工厂模式。
2. 同一个产品族的产品，它们之间打包在一起使用。

### 实际应用场景
1. 同一个产品族的产品。qq皮肤，窗口和菜单都属于同一个主题。
2. 不同操作系统的程序。按钮与文本框都是属于某一操作系统。