前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之 工厂模式

设计模式之 工厂模式

作者头像
用户3094376
发布2018-09-12 11:05:26
5320
发布2018-09-12 11:05:26
举报
文章被收录于专栏:gaoqin31

工厂设计模式又分为简单工厂模式,工厂方法模式,抽象工厂模式

简单工厂模式 : 简单工厂模式是属于创建型的设计模式,又叫做静态工厂方法模式,但不属于23种GOF设计模式,简单工厂模式是由一个工厂决定创建哪一类产品的实例,简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。

代码语言:javascript
复制
<?php
/**
 * 简单工厂模式
 */
interface IDB{
    public function connect();
    public function query();
}

class Mysql implements IDB{
    public function connect(){
        echo "连接mysql\n";
    }
    
    public function query(){
        echo "查询mysql\n";
    }
}

class SqlServer implements IDB{
    public function connect(){
        echo "连接sqlserver\n";
    }
    
    public function query(){
        echo "查询sqlserver\n";
    }
}

class DbFactory{
    public static $instance = null;
    public static function Create($dbname){
        switch($dbname){
            case 'mysql':
                self::$instance =  new Mysql();
                break;
            case 'sqlserver' : 
                self::$instance =  new SqlServer();
        }
        return self::$instance;
    }
}

class Client{
    public static  function main(){
        $db = DbFactory::Create('mysql');
        $db->connect();
        $db->query();
        
        $db = DbFactory::Create('sqlserver');
        $db->connect();
        $db->query();
    }
}
Client::main();

我们可以看到简单工厂设计模式包含了3个角色,IDB接口(抽象产品),Sqlserver类(具体产品类),Mysql类(具体产品类),工厂方法类

客户端无需关心sqlserver或者Mysql对象的过程,只需要调用工厂方法传入参数获取实例,参数可以定义为常量,当需要切数据库的时候,只需要增加对应数据库类,修改常量即可。如果客户端自己new,想想切库的感觉那叫一个酸爽。

优点: 对客户端隐藏了对象实例化细节,去除了客户端与具体的产品类之间的依赖

缺点:

  1.当需要增加新的产品时,需要修改工厂方法,违背了开闭原则(当然我们可以利用反射去创建对象,无需修改工厂方法,PHP甚至反射都不需要,直接通过变量创建对象)

  2.当产品很多时工厂方法逻辑会过于复杂

使用场景:

简单工厂模式适用客户端不用知道具体的产品类,只需要知道工厂方法类的情况,但是只适合创建少量的产品。

工厂方法模式:定义一个用于创建对象的接口,让子类决定将哪一个类实例化,工厂方法模式让一个类的实例化延迟到其子类

简单工厂模式在新增产品的时候需要修改工厂方法创建对象的逻辑,违反了开放封闭原则,根据依赖倒转原则,把工厂类抽象出一个接口,这个接口有一个create()方法,然后具体的工厂类实现这个接口,客户端调用对应的工厂方法就能得到需要的产品。

代码语言:javascript
复制
<?php
/**
 * 工厂方法模式
 */
interface IDB{
    public function connect();
    public function query();
}

interface IDbFactory{
    public function create();
}

class Mysql implements IDB{
    public function connect(){
        echo "连接mysql\n";
    }
    
    public function query(){
        echo "查询mysql\n";
    }
}

class SqlServer implements IDB{
    public function connect(){
        echo "连接sqlserver\n";
    }
    
    public function query(){
        echo "查询sqlserver\n";
    }
}

class MysqlFatory implements IDbFactory{
    public function create(){
        return new Mysql();
    }
}

class SqlServerFatory implements IDbFactory{
    public function create(){
        return new SqlServer();
    }
}

class Client{
    public static  function main(){
        $dbFactory = new MysqlFatory();
        $db = $dbFactory->create();
        $db->connect();
        $db->query();
        
        $dbFactory = new SqlServerFatory();
        $db = $dbFactory->create();
        $db->connect();
        $db->query();
    }
}
Client::main();

通过UML图我们可以看到工厂方法模式比简单工厂模式多了一个抽象工厂接口的角色,这个角色起所起到的作用就是使得简单工厂模式里工厂方法针对接口编程,而不是针对具体生成对象细节编程。这样以后新增了Orace数据库的时候只需要新增Oracle类和工厂方法类。

完全做到了对修改关闭。

优点 :除了拥有简单工厂对客户端隐藏了对象创建细节的优点外,工厂方法模式在新增产品的时候只需新增具体的产品类以及工厂方法类,做到了对修改关闭,不影响现有的业务逻辑

缺点 : 每次增加产品都要新增产品类,工厂方法类,造成系统复杂度越来越高

抽象工厂模式:提供一个创建一系列相关的或者相互依赖对象的接口,而无需指定它们具体的类

代码语言:javascript
复制
<?php
/**
 * 抽像工厂模式
 */
interface IDB{
    public function connect();
    public function query();
}

interface ICache{
    public function connect();
    public function get();
}

interface IFactory{
    public function creatDB();
    public function createCache();
}

class Mysql implements IDB{
    public function connect(){
        echo "连接mysql\n";
    }
    
    public function query(){
        echo "查询mysql\n";
    }
}

class SqlServer implements IDB{
    public function connect(){
        echo "连接sqlserver\n";
    }
    
    public function query(){
        echo "查询sqlserver\n";
    }
}

class MysqlCache implements ICache{
    public function connect(){
        echo "连接mysql缓存\n";
    }
    
    public function get(){
        echo "查询mysql缓存\n";
    }
}

class SqlServerCache implements ICache{
    public function connect(){
        echo "连接sqlserver缓存\n";
    }
    
    public function get(){
        echo "查询sqlserver缓存\n";
    }
}


class MysqlFatory implements IFactory{
    public function creatDB(){
        return new Mysql();
    }
    
    public function createCache() {
        return new MysqlCache();
    }
}

class SqlServerFatory implements IFactory{
    public function creatDB(){
        return new SqlServer();
    }
    
    public function createCache() {
        return new SqlServerCache();
    }
}


class Client{
    public static  function main(){
        $factory = new MysqlFatory();
        $db = $factory->creatDB();
        $db->connect();
        $db->query();
        
        $cache = $factory->createCache();
        $cache->connect();
        $cache->get();
        
        $factory = new SqlServerFatory();
        $db = $factory->creatDB();
        $db->connect();
        $db->query();
        
        $cache = $factory->createCache();
        $cache->connect();
        $cache->get();
    }
}
Client::main();

我们通过类图可以看到抽象工厂方法模式和工厂方法模式唯一的区别是产品接口里不仅仅只有一个方法,而是一系列方法,原先我们只能创建db实例,现在也可以创建cache实例,抽象工厂模式解决了工厂方法模式只能创建1系列产品的缺点,

但是新增一个产品系列需要修改抽象产品接口,具体的工厂类。

优点:除了隐藏对象创建细节,还可以创建多种系列的产品

缺点:增加新系列产品,需要需改抽象接口以及具体的工厂类

可能是我项目经验不够,实际项目中我们用的最多的就是简单工厂模式了,其它两种基本没用到过,简单工厂模式配合PHP变量创建对象即可消除其违反开闭原则的缺点。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017-09-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档