PHP解耦的三重境界(浅谈服务容器)

「七天自制PHP框架」已经开始连载,谢谢关注和支持!点击这里

阅读本文之前你需要掌握:PHP语法,面向对象

在完成整个软件项目开发的过程中,有时需要多人合作,有时也可以自己独立完成,不管是哪一种,随着代码量上升,写着写着就“失控”了,渐渐“丑陋接口,肮脏实现”,项目维护成本和难度上升,到了难以维持的程度,只有重构或者重新开发。

第一重境界

假设场景:我们需要写一个处理类,能够同时操作会话,数据库和文件系统。我们或许会这么写。

境界特征:可以运行,但是严重耦合


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28


class DB{

    public function DB($arg1,$arg2){

        echo ‘constructed!‘.PHP_EOL;

    }

}

class FileSystem{

    public function FileSystem($arg1,$arg2){

        echo ‘constructed!‘.PHP_EOL;

    }

}

class Session{

    public function Session($arg1,$arg2){

        echo ‘constructed!‘.PHP_EOL;

    }

}

class Writer{

    public function Write(){

        $db=new DB(1,2);

        $filesystem=new FileSystem(3,4);

        $session=new Session(5,6);

    }

}

$writer=new Writer();

$writer->write();

写法缺点:

1.在公有函数中构造对象,一旦涉及到如数据库参数的变动,修改会有很大的工作量

2.负责设计Writer类的人员需要对DB等类的各种API要熟悉

有没有办法降低耦合度?

第二重境界(参数依赖)

假设场景:数据库地址因为客户不同,需要经常更换,调用到DB的类很多(假如有几十个),希望即使更改了数据库地址,也不用去修改这些类的代码。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39


class DB{

    public function DB($arg1,$arg2){

        echo ‘constructed!‘.PHP_EOL;

    }

}

class FileSystem{

    public function FileSystem($arg1,$arg2){

        echo ‘constructed!‘.PHP_EOL;

    }

}

class Session{

    public function Session($arg1,$arg2){

        echo ‘constructed!‘.PHP_EOL;

    }

}

class Writer{

    protected $_db;

    protected $_filesystem;

    protected $_session;

    public function Set($db,$filesystem,$session){

        $this->_db=$db;

        $this->_filesystem=$filesystem;

        $this->_session=$session;

    }

    public function Write(){

        

    }

}

$db=new DB(1,2);

$filesystem=new FileSystem(3,4);

$session=new Session(5,6);

$writer=new Writer();

$writer->Set($db,$filesystem,$session);

$writer->write();

虽然把DB类的构造移到了客户端,一旦涉及修改,工作量大大降低,但是新问题来了:为了创建一个Writer类,我们需要先创建好DB类,FileSystem类等,这对负责涉及Writer类的人来说,要求是很高的,他需要看很多其他类文档,一个个创建(可能还需要初始化),然后才能创建出他要的writer变量。

所以,我们希望,能有一种更好的写法,使得写Writer类的人,用一种更加快捷的接口,就能创建和调用他要的类,甚至连参数都不用填。

第三重境界(IOC容器)

经过前两重境界,我们希望能新增以下这些好处:

1.希望DB类,Session类,FileSystem类“拿来即用”,不用每次繁琐的初始化,比如写$db=new DB(arg1,arg2);这类语句。

2.希望DB等类型的对象是“全局”,在整个程序运行期间,随时可以调用。

3.调用DB等类型的程序员不用知道这个类太多的细节,甚至可以用一个字符串的别名来创建这样一个对象。

能够实现以上目标的就是IOC容器,可以把IOC容器简单的看成一个全局变量,并用关联数组把字符串和构造函数做绑定。

我们先实现一个容器类


1

2

3

4

5

6

7

8

9


class Container{

    public $bindings;

    public function bind($abstract,$concrete){

        $this->bindings[$abstract]=$concrete;

    }

    public function make($abstract,$parameters=[]){

        return call_user_func_array($this->bindings[$abstract],$parameters);

    }

}

服务注册(绑定)


1

2

3

4

5

6

7

8

9

10

11

12


$container=new Container();

$container->bind(‘db‘,function($arg1,$arg2){

    return new DB($arg1,$arg2);

});

$container->bind(‘session‘,function($arg1,$arg2){

    return new Session($arg1,$arg2);

});

$container->bind(‘fs‘,function($arg1,$arg2){

    return new FileSystem($arg1,$arg2);

});

容器依赖


1

2

3

4

5

6

7

8

9

10

11

12

13


class Writer{

    protected $_db;

    protected $_filesystem;

    protected $_session;

    protected $container;

    public function Writer(Container $container){

        $this->_db=$container->make(‘db‘,[1,2]);

        $this->_filesystem=$container->make(‘session‘,[3,4]);

        $this->_session=$container->make(‘fs‘,[5,6]);

    }

}

$writer=new Writer($container);

时间: 2024-08-25 09:46:36

PHP解耦的三重境界(浅谈服务容器)的相关文章

浅谈C++容器动态内存管理的优化

在信息学竞赛中,C++的容器的用途非常广泛,但经常因常数过大而超时.怎样才能提高它们的效率呢? 我们知道,容器是存储同一类对象的对象,既然"对象"我们无法改变,那么我们只能从"存储"入手,不难想到,不同容器在实现上的根本区别是它们对应着不同的内存组织方式,内存管理无疑是这种实现的核心,所以优化内存管理是加快容器效率的最好途径之一. 一.内存分配器简介 怎样才能优化内存管理呢?很简单,C++为我们提供了这样的接口,我们可以通过自定义容器模板中的最后一个allocato

浅谈服务意识

网上查资料,无意翻到一则去年的新闻:这个新闻的主人公是名会计,在去办理所得税的年报申报时,那里的工作人员不但牺牲了自己的午休时间,还给她端来了午饭.本来是很快就能办好的业务,但是这位会计自己不会操作,拖延了很长的时间.快到下班的时间了,一旁的税务干部看到她那么急迫,就过来指导,帮助她把剩下的业务办完.耽误到工作人员的午休,还能这么耐心地帮她办理业务,这已经让她心里很感谢了,没想到因为是午饭时间,这里的工作人员还给他端来了午饭.这位会计感动得不得了,所以特地将这碗饭拍照做了纪念,特地联系记者做报道

浅谈服务架构“五脏六腑”之Spring Cloud

本文将从 Spring Cloud 出发,分两小节讲述微服务框架的「五脏六腑」: 第一小节「服务架构」旨在说明的包括两点,一服务架构是什么及其必要性:二是服务架构的基本组成.为什么第一节写服务架构而不是微服务架构呢?原因主要是微服务架构本身与服务架构有着千丝万缕的关系,服务架构是微服务架构的根基. 第二小节「五脏六腑」则将结合 Spring Cloud 这个特例来介绍一个完整的微服务框架的组成. 服务架构 为了方便理解,我先讲一个小故事:(改编自一知乎答主) Martin(微服务提出者也叫 Ma

浅谈Linux容器和镜像签名

导读 从根本上说,几乎所有的主要软件,即使是开源软件,都是在基于镜像的容器技术出现之前设计的.这意味着把软件放到容器中相当于是一次平台移植.这也意味着一些程序可以很容易就迁移,而另一些就更困难. 我大约在三年半前开展基于镜像的容器相关工作.到目前为止,我已经容器化了大量应用.我了解到什么是现实情况,什么是迷信.今天,我想简要介绍一下 Linux 容器是如何设计的,以及谈谈镜像签名. Linux 容器是如何设计的 对于基于镜像的 Linux 容器,让大多数人感到困惑的是,它把操作系统分割成两个部分

<转载>浅谈c++容器系列

以下资料转自CSDN 某牛人.对c++容器有一个比较好的理解: http://blog.csdn.net/acosoft/article/details/4395468 http://blog.csdn.net/acosoft/article/details/4398367 http://blog.csdn.net/acosoft/article/details/4404981 http://blog.csdn.net/acosoft/article/details/4411332 http:/

浅谈List容器

List容器 从根源来说Set.List.Queue这三个接口都继承于Collection接口,Set为数据集,List为列表,Queue为队列 下面,我们来说一说List List的实现包括ArrayList.LinkedList.Vector,我们主要说一说前两者,因为第三个我还没接触到(- ̄▽ ̄)- 1.ArrayList 本质是一个自动扩展的数组,有序.可重复.可以为null ArrayList是一个容器和数组并没有什么样的不同,不同点在于数据出去的多样化(三种):普通for.增强for

从读取properties文件说开去,浅谈web容器中类加载器

今天刚好有人让我写个通过读取properties连接数据库的小demo. 汗啊,普通项目中可以使用的文件读取,在web项目中总报空指针异常. 查阅了资料明白,赶紧记录下来,希望遇到此类问题的童鞋能引起重视. 废话不说,直接进入主题! 代码清单1: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.io.InputStream; import java.util.Properties; import org.apache.log4

浅谈微服务架构与服务治理的Eureka和Dubbo

前言 本来计划周五+周末三天自驾游,谁知人算不如天算,周六恰逢台风来袭,湖州附近的景点全部关停,不得已只能周五玩完之后,于周六踩着台风的边缘逃回上海.周末过得如此艰难,这次就聊点务虚的话题,一是浅谈微服务的架构设计,二是聊聊微服务中广泛用于服务治理的Eureka与RPC框架Dubbo异同点. 一.微服务的架构设计 之所以想聊一下这个话题,主要有感于最近接触的两个新的微服务项目--两个项目的架构设计出自两个人之手,却不约而同的使用了相同的设计理念,项目结构非常类似.又想到就职于上家公司时接触到的项

【转】浅谈分布式服务协调技术 Zookeeper

非常好介绍Zookeeper的文章, Google的三篇论文影响了很多很多人,也影响了很多很多系统.这三篇论文一直是分布式领域传阅的经典.根据MapReduce,于是我们有了Hadoop:根据GFS,于是我们有了HDFS:根据BigTable,于是我们有了HBase.而在这三篇论文里都提及Google的一个Lock Service —— Chubby,哦,于是我们有了Zookeeper. 随着大数据的火热,Hxx们已经变得耳熟能详,现在作为一个开发人员如果都不知道这几个名词出门都好像不好意思跟人