大话设计模式(php版)第一章——简单工厂模式

前言

小菜去面试,前台给他一份题,上面写道"请使用面向对象语言实现一个计算器控制台程序,要求输入两个数,得到结果"

小菜的第一次修改

<?php

$A = $_POST['A'];
$B = $_POST['B'];
$C = $_POST['C'];
$D = '';

if($B == '+')
    $D = round($A + $C ,2);
if($B == '-')
    $D = round($A - $C ,2);
if($B == '*')
    $D = round($A * $C ,2);
if($B == '/')
    $D = round($A / $C ,2);

echo '结果是: '. $D;

大鸟指导

  1. A,B,C 命名不规范

  2. 写了四个判断分支,意味着每个条件都要做判断,等于计算机做了三次无用功

  3. 除法没考虑到除数为0的情况

小菜的第二次修改

<?php

try {
    $numberA = $_POST['number_a'];
    $operate = $_POST['operate'];
    $numberB = $_POST['number_b'];
    $result = '';

    switch ($operate) {
        case   '+':
            $result = round($numberA + $numberB, 2);
            break;
        case   '-':
            $result = round($numberA - $numberB, 2);
            break;
        case   '*':
            $result = round($numberA * $numberB, 2);
            break;
        case   '/':
            if ($numberB != 0) {
                $result = round($numberA / $numberB, 2);
            } else {
                $result = '除数不能为0';
            }
            break;
    }

    echo '结果是: ' . $result;
} catch (Exception $e) {
    echo '您的输入有误: ' . $e->getMessage();
}

大鸟指导(上)

这份代码实现计算器是没有问题了,但是这个代码是否符合面向对象呢?什么是面向对象?来听听这个故事

曹操吟诗的故事

话说三国时期,曹操带领百万大军攻打东吴,大军在长江赤壁驻扎,军船连成一片,眼看就要灭掉东吴,统一天下,曹操大悦,于是大宴众文武,在酒席间,曹操诗兴大发,不觉吟道: " 喝酒唱歌,人生真爽 … ". 众文武齐呼: “宰相好诗!” 于是一臣子速命刻板印刷,以便流传天下.
样张出来,曹操一看,觉得不妥,说到 “唱与喝,此话过俗,应改为’对酒当歌’较好!”,于是此臣就命工匠重新来过.工匠眼看连夜刻板之工,彻底白费.心中叫苦不迭,只得照办.
样张再次出来,曹操细细一品,觉得还是不好,说 "人生太爽太过直接,应改为问句才够意境,应改为’对酒当歌,人生几何?’ …"当臣转告工匠之时,工匠晕倒 …

问题出在哪里?

如果当时有活字印刷,而不是整个刻板重新刻,就不会有这些问题

活字印刷的优点

  1. 要改需要改动的字,此为可维护
  2. 未用到的字并非无用,完全可以在之后的印刷中重复使用,此为可复用
  3. 如果要加字,只需要另刻字加入即可,此为可扩展
  4. 字的排列可以横着可以竖着,只需要移动活字即可,此为灵活性好

大鸟指导(下)

你这份代码有哪些是和控制台无关,只和计算器有关的?把它们抽离出来,降低它的耦合度,便于维护或扩展

小菜的第三次修改

<?php

class Operation
{
    public function getResult($numberA, $numberB, $operate)
    {
        $result = '';
        switch ($operate) {
            case   '+':
                $result = round($numberA + $numberB, 2);
                break;
            case   '-':
                $result = round($numberA - $numberB, 2);
                break;
            case   '*':
                $result = round($numberA * $numberB, 2);
                break;
            case   '/':
                if ($numberB != 0) {
                    $result = round($numberA / $numberB, 2);
                } else {
                    $result = '除数不能为0';
                }
                break;
        }
        return $result;
    }
}


try {
    $numberA = $_POST['number_a'];
    $operate = $_POST['operate'];
    $numberB = $_POST['number_b'];

    $result = (new Operation())->getResult($numberA, $numberB, $operate);
    echo '结果是: ' . $result;
} catch (Exception $e) {
    echo '您的输入有误: ' . $e->getMessage();
}

大鸟指导

仅此而已,还谈不上完全面向对象,这里仅用了面向对象三大特性之一[封装]
想想如何使用面向对象的继承多态

  • 如果让你新增一个开根(sqrt)运算,你如何改?
  • 如果在switch加一个分支,意味着加减乘除的运算都得参与编译
  • 如果你一不小心,改动了别的代码,岂不是凉凉?

小菜的第四次修改

<?php

class operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        $this->numberA = $numberA;
        $this->numberB = $numberB;
    }

    public function getResult()
    {
        return 0;
    }
}

class operationAdd extends Operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        parent::__construct($numberA, $numberB);
    }

    public function getResult()
    {
        return round($this->numberA + $this->numberB, 2);
    }
}

class operationSub extends Operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        parent::__construct($numberA, $numberB);
    }

    public function getResult()
    {
        return round($this->numberA - $this->numberB, 2);
    }
}

class operationNul extends Operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        parent::__construct($numberA, $numberB);
    }

    public function getResult()
    {
        return round($this->numberA * $this->numberB, 2);
    }
}

class operationDiv extends Operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        parent::__construct($numberA, $numberB);
    }

    public function getResult()
    {
        if ($this->numberB == 0) {
            throw new \Exception('除数不能为0');
        }
        return round($this->numberA / $this->numberB, 2);
    }
}

大鸟指导

现在对面向对象运用的淋漓尽致了,下面学习下简单工厂模式

简单工厂模式

<?php

class operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        $this->numberA = $numberA;
        $this->numberB = $numberB;
    }

    public function getResult()
    {
        return 0;
    }
}

class operationAdd extends Operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        parent::__construct($numberA, $numberB);
    }

    public function getResult()
    {
        return round($this->numberA + $this->numberB, 2);
    }
}

class operationSub extends Operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        parent::__construct($numberA, $numberB);
    }

    public function getResult()
    {
        return round($this->numberA - $this->numberB, 2);
    }
}

class operationNul extends Operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        parent::__construct($numberA, $numberB);
    }

    public function getResult()
    {
        return round($this->numberA * $this->numberB, 2);
    }
}

class operationDiv extends Operation
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        parent::__construct($numberA, $numberB);
    }

    public function getResult()
    {
        if ($this->numberB == 0) {
            throw new \Exception('除数不能为0');
        }
        return round($this->numberA / $this->numberB, 2);
    }
}

class operationFactory
{
    protected $numberA = 0;
    protected $numberB = 0;

    public function __construct($numberA, $numberB)
    {
        $this->numberA = $numberA;
        $this->numberB = $numberB;
    }

    public function createOperate($operate)
    {
        $obj = null;
        switch ($operate) {
            case '+':
                $obj = new operationAdd($this->numberA, $this->numberB);
                break;
            case '-':
                $obj = new operationSub($this->numberA, $this->numberB);
                break;
            case '*':
                $obj = new operationNul($this->numberA, $this->numberB);
                break;
            case '/':
                $obj = new operationDiv($this->numberA, $this->numberB);
                break;
        }
        return $obj;
    }
}

//测试调用
$obj = new operationFactory(2, 3);
echo $obj->createOperate('*')->getResult();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值