以OOP之名--重构PHP代码小教程(2)

前言:前面0-1完整讲解了TennisGame的重构过程。本节将以一个Insurance的例子继续。本节将使用到一点点无伤大雅的PHPUnit。

注意:PHPUnit的安装过程略过,我使用的是PHP7.1,所以,用到了PHPUnit 7.5.20的安装包。而且,不同版本的PHPUnit的手册差异比较大,在展示的代码或许无法在你的PHP环境中正确运行。这部分的PHPUnit可以忽略。

原始代码

注意:这里的原始代码中的链接是一个无意义的链接,仅为了演示代码重构使用,关键是var_dump返回的那个array

<?php

class Insurance{
	public function quote($providers = null)
	{
		if(!$providers){
			$providers = ['bank','insurance-company'];
		}else{
			$providers = [$providers];
		}
		$quote = array();
		$bank_url = 'https://www.baidu.com/';
		for($i = 0;$i<count($providers);++$i){
			switch($providers[$i]){
				case 'bank':
					$prices = file_get_contents($bank_url);
				case 'insurance-company':
					$curl = curl_init();
					curl_setopt_array($curl,array(
						CURLOPT_RETURNTRANSFER=>1,
						CURLOPT_URL=>'HTTP://123.COM/',
						CURLOPT_POST=>1,
						CURLOPT_POSTFIELDS=>array(
							'month'=>3,
							)
						));
					$prices = json_decode(curl_exec($curl));
					curl_close($curl);
			}
			$quote[$providers[$i]] = $prices;
		}
		return $quote;
	}
}

$insurance = new Insurance();
$quote = $insurance->quote();
var_dump($quote);

?>

 可以使用命令行php Insurance.php测试一下。

与之对应的文档test文件是InsutanceTest.test.php

<?php


class InsuranceTest extends PHPUnit_Framework_TestCase{
	public function testQuoteNotNull(){
		require './Insurance.php';
		$insurance = new Insurance();
		$quote = $insurance->quote();
		$this->assertNotNull($quote['bank']);
		$this->assertNotNull($quote['insurance-company']);
	}
}

?>

命令行输入phpunit InsuranceTest.test.php测试一下。
 

Step 0:构造函数,以及providers 的 OOP化

通过这个construct方法,就可以把如下内容取代:

		 if(!$providers){
		 	$providers = ['bank','insurance-company'];
		 }else{
		 	$providers = [$providers];
		 }
<?php

class Insurance{

	protected $providers;

	public function __construct(Provider $provider = null){
		$this->providers = $provider ? [$provider]:[new BankProvider(),new InsuranceCompanyProvider()];
	}

	public function quote($providers = null)
	{
		$quote = array();

		$bank_url = 'https://www.baidu.com/';
		for($i = 0; i<count($this->providers);++$i){
		// foreach($this->providers as $provider){
			switch($this->providers[$i]){
				case 'bank':
					$prices = file_get_contents($bank_url);
				case 'insurance-company':
					$curl = curl_init();
					curl_setopt_array($curl,array(
						CURLOPT_RETURNTRANSFER=>1,
						CURLOPT_URL=>'HTTP://123.COM/',
						CURLOPT_POST=>1,
						CURLOPT_POSTFIELDS=>array(
							'month'=>3,
							)
						));
					$prices = json_decode(curl_exec($curl));
					curl_close($curl);
			}
			$quote[$this->getName()] = $this->provides[$i]->getPrices();
		}
		return $quote;
	}
}


abstract class Provider{

}

class BankProvider extends Provider{

}

class InsuranceCompanyProvider extends Provider{

}



$insurance = new Insurance();
$quote = $insurance->quote();
var_dump($quote);

?>

Step 1: bank类型prices的OOP化,顺便把for改成foreach

<?php

class Insurance{

	protected $providers;

	public function __construct(Provider $provider = null){
		$this->providers = $provider ? [$provider]:[new BankProvider(),new InsuranceCompanyProvider()];
	}

	public function quote($providers = null)
	{
		$quote = array();

		foreach($this->providers as $privder){
		// foreach($this->providers as $provider){

			$quote[$privider->getName()] = $provide->getPrices();
		}
		return $quote;
	}
}


abstract class Provider{
	abstract function getPrices();
	abstract function getName();
}

class BankProvider extends Provider{
	public function getName(){
		return 'bank';
	}

	public function getPrices(){
		$bank_url = 'https://www.baidu.com/';
		$prices = file_get_contents($bank_url);
		return $prices;
	}
}

class InsuranceCompanyProvider extends Provider{
	public function getName(){
		return 'insurance-company';
	}
	public function getPrices(){
		$curl = curl_init();
		curl_setopt_array($curl,array(
			CURLOPT_RETURNTRANSFER=>1,
			CURLOPT_URL=>'HTTP://123.COM/',
			CURLOPT_POST=>1,
			CURLOPT_POSTFIELDS=>array(
				'month'=>3,
				)
			));
		$prices = json_decode(curl_exec($curl));
		curl_close($curl);
		return $prices;
	}
}



$insurance = new Insurance();
$quote = $insurance->quote();
var_dump($quote);

?>

可以测试一下

Step 2:进一步把curl解决掉

这个步骤也就是让大家看个思路,由于我没有找到合适的json服务器,所以无法演示器结果。

<?php

class Insurance{

	protected $providers;

	public function __construct(Provider $provider = null){
		$this->providers = $provider ? [$provider]:[new BankProvider(),new InsuranceCompanyProvider()];
	}

	public function quote($providers = null)
	{
		$quote = array();

		foreach($this->providers as $privder){
		// foreach($this->providers as $provider){

			$quote[$privider->getName()] = $provide->getPrices();
		}
		return $quote;
	}
}


abstract class Provider{
	protected $url =  'https://www.baidu.com/';
	abstract function getPrices();
	abstract function getName();
}

class BankProvider extends Provider{
	public function getName(){
		return 'bank';
	}

	public function getPrices(){
		$url = $this->url.'/bank';

		$prices = Curl::exec($url);
		return $prices;
	}
}

class Curl{
	public static function exec($url,$opt = []){
		$curl = curl_init();
		$options = [
			CURLOPT_RETURNTRANSFER=>1,
			CURLOPT_URL=>$url,
		];
		if($opt){
			$options[CURLOPT_POST] = 1;
			$options[CURLOPT_POSTFIELDS] = http_build_query($opt); 
		}

		curl_setopt_array($curl,$options);
		$result = curl_exec($curl);
		curl_close($curl);
		return $result;
	}
}
class InsuranceCompanyProvider extends Provider{
	public function getName(){
		return 'insurance-company';
	}
	public function getPrices(){
		$url = $this->url.'/insurance';
		
		$prices = Curl::exec($url,[
				'month'=>3
			]);

		return $prices;
	}
}



$insurance = new Insurance();
$quote = $insurance->quote();
var_dump($quote);

?>

Step 3: 最后一步

<?php

class Insurance{

	protected $providers;
	protected $curl;
	public function __construct(ICurl $curl, Provider $provider = null){
		$this->providers = $provider ? [$provider]:[new BankProvider(),new InsuranceCompanyProvider()];
		$this->curl = $curl;
	}

	public function quote($providers = null)
	{
		$quote = array();

		foreach($this->providers as $provider){

			$quote[$provider->getName()] = $provide->getPrices($this->curl);
		}
		return $quote;
	}
}


abstract class Provider{
	protected $url =  'https://www.baidu.com/';
	abstract function getPrices(ICurl $curl);
	abstract function getName();
}

class BankProvider extends Provider{
	public function getName(){
		return 'bank';
	}

	public function getPrices(ICurl $curl){
		$url = $this->url.'/bank';

		$prices = $curl->exec($url);
		return $prices;
	}
}
interface ICurl{
	public function exec($url, $opt=[]);
}

class Curl implements ICurl{
	public function exec($url,$opt = []){
		
		try{
			$curl = curl_init();
			$options = [
				CURLOPT_RETURNTRANSFER=>1,
				CURLOPT_URL=>$url,
			];
			if($opt){
				$options[CURLOPT_POST] = 1;
				$options[CURLOPT_POSTFIELDS] = http_build_query($opt); 
			}

			curl_setopt_array($curl,$options);
			$result = curl_exec($curl);
			curl_close($curl);
			return $result;
		}catch(Exception $e){
			throw new Exception($e);
		}
	}
}
class InsuranceCompanyProvider extends Provider{
	public function getName(){
		return 'insurance-company';
	}
	public function getPrices(ICurl $curl){
		$url = $this->url.'/insurance';
		
		$prices = $curl->exec($url,[
				'month'=>3
			]);

		return $prices;
	}
}


$curl = new Curl();
$insurance = new Insurance($curl);
$quote = $insurance->quote();
var_dump($quote);

?>
<?php

require './Insurance.php';
class InsuranceTest extends PHPUnit_Framework_TestCase{
	public function testQuoteNotNull(){
		require './Insurance.php';

		$curl = new Curl();
		$insurance = new Insurance($curl);
		$quote = $insurance->quote();
		$this->assertNotNull($quote['bank']);
		$this->assertNotNull($quote['insurance-company']);
	}
	public function testCurlSuccess(){
		require './Insurance.php';

		$curl = new CurlSuccess();
		$insurance = new Insurance($curl);
		$quote = $insurance->quote();
		$this->assertNotNull($quote['bank']);
		$this->assertNotNull($quote['insurance-company']);
	}

	public function testCurlFail(){
		require './Insurance.php';
		$curl = new CurlSuccess();
		$insurance = new Insurance($curl);
		$this->exceptException(Exception::class);
		$quote = $insurance->quote();
	}
}
class CurlSuccess implements ICurl{
	public function exec($url, $opt = [])
	{
		return ['success'];
	}
}

class CurlFail implements ICurl{
	public function exec($url, $opt = [])
	{
		throw new Exception('Failed');
	}
}
?>

后记:这篇blog写得太痛苦了,大家讲究看吧。完工

猜你喜欢

转载自blog.csdn.net/yaoguoxing/article/details/107131625