0

我有这个结构:

abstract class Android {
    public function __construct() {

    }

    public abstract function cost();

    public function get_model(){
        return "unkown model";
    }
}

class HTC extends Android {

    public function __construct() {
        parent::__construct();
        $this->model= "HTC";
    }

    public function get_model() {
        return $this->model;
    }

    public function cost() {
        return 500;
    }
}

abstract class FeaturesDecorator extends Android {
    public function __construct() {
        parent::__construct();
    }

    public abstract function get_description();
}

class VideoCamera extends FeaturesDecorator {
    private $android;

    public function __construct($android) {
        parent::__construct();
        $this->android=$android;
    }

    public function get_description() {
         return $this->android->get_model()." plus a video camera, ";
    }

    public function cost() {
        return 200 + $this->android->cost();
    }
}

class BigScreenSize extends FeaturesDecorator {
    private $android;

    public function __construct($android) {
        parent::__construct();
        $this->android=$android;
    }

    public function get_description() {
        return $this->android->get_model()." plus a big size screen, ";  
    }

    public function cost() {
        return 100 + $this->android->cost();
    }
}

应用以下模式后:

$android2 = new HTC();
$android2 = new BigScreenSize($android2);
$android2 = new LongLastingBattery($android2);

echo "<br/><br/>You have bought ".$android2->get_description()." for $".$android2->cost();

我明白了

您以 650 美元的价格购买了 Unkown 品牌和长效电池

再次:

我想知道为什么我得到Unknown brand而不是HTCfromget_model()调用get_description()$650被正确计算

4

3 回答 3

0

When i first tested your code, php told me that the class LongLastingBattery does not exist, which is correct - it doesn't. I assume you meant VideoCamera; so your main function in my answer will begin with this:

$android2 = new HTC();
$android2 = new BigScreenSize($android2);
$android2 = new VideoCamera($android2);

Your problem is that you are simply confusing the two methods get_description() and get_model(): You first call get_description() on the VideoCamera instance. There you have $this->android->get_model() where $this->android is an instance of BigScreenSize. The class BigScreenSize does not override the method get_model(). BigScreenSize extends FeaturesDecorator, that does not override this method either but extends Android, that has this method and returns "unknown model".

To overcome this problem you could change $this->android->get_model() into $this->android->get_description() in both VideoCamera and BigScreenSize and rename the get_model() method in both Android and HTC into get_description(). Finally, you have to change FeaturesDecorator into this:

abstract class FeaturesDecorator extends Android {}

Then you'll get this:

<br/><br/>You have bought HTC plus a big size screen,  plus a video camera,  for $800
于 2013-01-24T14:42:22.497 回答
-1

你的FeatureDecorator继承自Android,而不是HTC。所以第一次添加装饰时,$android2将是 typeAndroid而不是之前的HTC.

也许你的意思是:

abstract class FeaturesDecorator extends HTC {
  // ...
}

这应该为您的示例提供正确的输出。


编辑你可以将你的model成员变量移动到Android类;也应该工作:

abstract class Android {
  protected $model = "unknown model";

  public function get_model() {
    return $this->model;
  }
}

这种方式model直接存储在 中Android,可以从所有子类中设置,并且可以从任何其他持有 Android对象引用的类中检索。

于 2012-07-16T20:00:03.620 回答
-1
$android1=new HTC();
$android2=new BigScreenSize($android1);
$android3=new VideoCamera($android2);

在 $android2 和 3 上执行 var_dump 将为您提供它们持有的对象(必须更改为摄像机,因为您提供的代码中不存在电池类)并且 android3 持有 bigscreensize 对象而不是 htc,因此是“未知”。如果你想获得你的结果('HTC'),你必须(首先让 $android 公开而不是私有)和

echo $android3->android->get_description();

或根据您的示例(仍然在您的课程中公开 $android)

echo $android2->android->get_description();

应用这些更改给了我:

您以 800 美元的价格购买了 HTC 和大尺寸屏幕

最后,我仍然坚持我最初的想法,即你应该修改你所采取的方法。也许添加一个方法,从它的父级获取 $model 并在构造函数中使用它。这样您就可以跟踪模型并使用本地属性。(在我上面的示例中,摄像机在执行 get_description() 时尝试访问 bigscreensize->get_model(),此方法在 bigscreensize 中不存在,但在作为 bigscreensize 父级的父级的 android 中存在。继承在这里工作得很好。请注意,您的装饰器不知道 htc 类的存在,因此除非您为所有装饰器提供访问/传递“模型”变量的方法。通过第一个装饰器,您将无法访问它。cost() 有效,因为它存在在每个班级。

我应该在昨晚回答之前阅读这个问题。对不起。

于 2012-07-16T23:22:32.087 回答