在此先感谢您的帮助和指导.我终于完成了从线性编程到OOP的转换.我正在上第一堂课,我可以用一点方向.我的第一堂课是一个具有以下属性的画廊
class Gallery
{
//Gallery Name
public $galleryID;
public $galleryName;
//Client Name
public $clientName;
//Gallery Options
public $bg_color;
public $albumAgreement;
public $maxChanges;
public $sharing_on;
//Revisions
public $revisions;
}
Run Code Online (Sandbox Code Playgroud)
因此我的出局看起来像:
Gallery Object
(
[galleryID] =>
[galleryName] =>
[clientName] =>
[bg_color] =>
[albumAgreement] =>
[maxChanges] =>
[sharing_on] =>
[revisions] =>
)
Run Code Online (Sandbox Code Playgroud)
我的下一步是我想将'revisions'作为一个对象,以便我的输出看起来像
Gallery Object
(
[galleryID] =>
[galleryName] =>
[clientName] =>
[bg_color] =>
[albumAgreement] =>
[maxChanges] =>
[sharing_on] =>
[revisions] => Revisions Object (
[revisionID] =>
[revisionName] =>
)
)
Run Code Online (Sandbox Code Playgroud)
我有什么方向可以选择这样的课程以及课程的样子?
谢谢
rdl*_*rey 22
这更像是一个长篇评论,因为它解释了你的困境的根源,但没有提供任何解决方案.
对象中的公共属性很少有很好的用例.让我们看一下OP的例子:
class Gallery {
public $galleryID;
public $galleryName;
// ...
}
Run Code Online (Sandbox Code Playgroud)
定义了我们的属性后public,以下两个代码片段有何不同?
$gallery = new Gallery;
$gallery->galleryId = 42;
$gallery->galleryName = 'some name';
// vs:
$gallery = array(
'galleryId' => 42,
'galleryName' => 'some name'
);
Run Code Online (Sandbox Code Playgroud)
如果你说,"它们根本没有什么不同",那么你就是对的.实际上,由于涉及的实例化开销,基于对象的代码将更慢new.还有一些其他因素,例如能够传递对象的引用而不是复制新数组,但这些因素不会影响这种特定情况.
创建一个只是可变属性集合的对象的问题是,其余代码完全了解该对象内部发生的事情.我们来谈谈为什么这很糟糕......
在复杂性方面,人类只是不太好.良好的软件旨在通过将功能封装到离散单元中来最小化复杂性.在这种情况下,我们希望将"gallery"实体的所有逻辑封装到Gallery类中.这是域驱动设计(DDD)方法的一部分.我们想要做的就是隔离Gallery外界世界; 我们希望它的内部实现对我们的其余代码不透明.我们应用程序的其余部分不应该知道或关心Gallery函数如何,只是它按预期工作.这里的额外好处是我们可以专注于使画廊按照预期工作然后忘记它.我们不会被记住如何Gallery与a Image或a 一起工作Revision.这种松耦合是OO设计中最强大的工具之一.
虽然它可能在非常小的范围内工作,但是不可能同时保持整个应用程序的逻辑.无论你有多聪明,我们的大脑都没有足够的RAM.
回到代码,如果我们的应用程序代码知道如何Gallery为自己分配名称,那么我们已经允许"gallery-ness"的逻辑泄漏到程序的其余部分.当我们决定在分配时验证新的图库名称时会发生什么?我们现在必须在我们指定图库名称的代码中随处放置验证逻辑,因为我们没有关于"gallery-ness"抽象概念的所有内容.更好的设计是Gallery在对象本身内封装属性的赋值:
class Gallery {
private $galleryId;
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName($name) {
return $this->name;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我们以这种方式构建我们的类,当我们需要为库指定名称时,我们总是只有一个入口点.现在,当我们对画廊的要求发生变化时(他们会),我们所有的应用程序代码 - 与图库名称分配背后的逻辑无关 - 都与破损隔离开来.我们只需在名称设置器中添加一个新方法,并在程序中创建最小的剧变:
class Gallery {
private $galleryId;
private $name;
public function setName($name) {
$this->validateName($name);
$this->name = $name;
}
private function validateName($name) {
if (!preg_match('/^[a-z]+$/', $name)) {
throw new Exception;
}
}
public function getName($name) {
return $this->name;
}
}
Run Code Online (Sandbox Code Playgroud)
要回答如何将封装Revision对象表示为更高级别Gallery实例的属性的问题,我们需要一些上下文.看来OP正在尝试做的是模型域实体,它将被写入后端持久层(例如数据库,平面文本文件等)并从中检索.
贫血领域模型是处理这种情况的一种方式,但它通常被认为是反模式.马丁福勒写道:
贫血领域模型的基本症状是乍一看它看起来像真实的东西.有许多对象,其中许多以域空间中的名词命名,并且这些对象与真实域模型具有的丰富关系和结构相关联.当你看到这个行为时会发现这个问题,你会发现这些物体上几乎没有任何行为,这使得它们只不过是吸气剂和制定者的一部分.实际上,这些模型通常都带有设计规则,表明您不要将任何域逻辑放在域对象中.相反,有一组服务对象捕获所有域逻辑.这些服务位于域模型之上,并使用域模型进行数据.
考虑到这些参数,您应该考虑使用类似DataMapper或Gateway模式的东西来处理需要持久化到某种形式的后端存储的域对象.
让我们忘记Revision一分钟的对象,并想象我们想要使用一个Slideshow对象来输出图库中的图像.这个类看起来像:
class Slideshow {
private $gallery;
public function __construct(Gallery $gallery) {
$this->gallery = $gallery;
}
public function play() {
// do something with the gallery here
}
}
Run Code Online (Sandbox Code Playgroud)
忽略这样一个事实,即PHP代码实际上不会用于"播放"幻灯片,因为这会在客户端代码中发生.这里重要的Slideshow是使用Composition来访问Gallery.这种结构大大优于直接new荷兰国际集团一Gallery内部Slideshow原因:
该Slideshow是可拔插的-我们可以插入遵循"画廊性"的概念,任何对象(通常Gallery会被宣布为符合特定接口契约).
在Slideshow现在迫切测试.我们如何处理Gallery提供的图像类型不合适的情况?如果我们直接在实例化Gallery内部,Slideshow我们无法模拟这样的条件.通过注入Slideshow我们的依赖关系,我们有机会测试代码处理不同操作条件的能力.
当然,有时直接实例化另一个类中的对象是合适的.有关这个主题的更多指导,我建议MiškoHevery在他的文章To"new"或不是"new"中提出建议.
xbo*_*nez 10
好的是PHP是动态类型的,所以你的代码几乎保持不变.初始化时revisions,只需将其初始化为Revisions对象的实例,就像这样
$gallery = new Gallery();
$gallery->revisions = new Revisions() // assuming you have defined the Revisions class
Run Code Online (Sandbox Code Playgroud)
至于类应该是什么样的,基于你的var_dump,像这样:
class Revisions {
public $revisionID;
public $revisionName;
public function __construct($id, $name) {
$this->revisionID = $id;
$this->revisionName = $name;
}
// if required, define a default constructor as well that does not take any parameters
}
Run Code Online (Sandbox Code Playgroud)
由于revisions你的问题并不完全清楚,你可能想要创建一个Revision对象而不是Revisions(不是复数),然后$gallery->revisions成为一个数组Revision.
| 归档时间: |
|
| 查看次数: |
534 次 |
| 最近记录: |