- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我似乎无法理解策略模式提供的优势。请参见下面的示例。
//Implementation without the strategy pattern
class Registry {
public function Func1(){
echo 'called function 1';
}
public function Func2(){
echo 'called function 2';
}
}
$client = new Registry();
$client->Func1();
$client->Func2();
//Implementation with strategy pattern
interface registry {
public function printMsg();
}
class Func1 implements registry {
public function printMsg(){
echo 'called function 1';
}
}
class Func2 implements registry {
public function printMsg(){
echo 'called function 2';
}
}
class context {
public function printMsg(Registry $class){
$class->printMsg();
}
}
$client = new context();
$client->printMsg(new Func1());
$client->printMsg(new Func2());
在上面的两个示例中,策略模式将提供哪些优势,它比第一种方法有何优势?为什么要使用策略模式?
以上示例代码可能存在错误,请忽略该代码。
最佳答案
策略模式的目的是:
Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it. [GoF:349]
要理解这意味着什么,你必须(强调我的)
Consider what should be variable in your design. This approach is the opposite of focusing on the cause of redesign. Instead of considering what might force a change to a design, consider what you want to be able to change without redesign. The focus here is on encapsulating the concept that varies, a theme of many design patterns. [GoF:29]
换句话说,策略是相关的代码片段,您可以在运行时将其插入客户端(另一个对象)以更改其行为。这样做的一个原因是为了防止每次添加新行为时都必须接触客户端(参见 Open Closed Principle (OCP) 和 Protected Variation )。此外,当你有足够复杂的算法时,将它们放入自己的类中,有助于遵守 Single Responsibility Principle (SRP) .
我发现您问题中的示例不太适合理解策略模式的用途。 Registry 不应该有 printMsg()
方法,我无法理解这个例子本身。一个更简单的例子是我在 Can I include code into a PHP class? 中给出的例子(我谈论策略的部分从答案的一半开始)。
但无论如何,在您的第一段代码中,Registry 实现了方法 Func1 和 Func2。由于我们假设这些是相关算法,让我们假装它们真的是 persistToDatabase()
和 persistToCsv()
来让我们思考一些事情。我们还想象一下,在应用程序请求结束时,您从 shutdown handler 调用这些方法之一。 (客户端)。
但是哪种方法呢?好吧,这取决于您配置的内容,并且该标志显然存储在注册表本身中。所以在你的客户中你最终会得到类似的东西
switch ($registry->persistStrategy)
{
case 'database':
$registry->persistToDatabase();
case 'csv':
$registry->persistToCsv();
default:
// do not persist the database
}
但是像这样的 switch 语句是不好的(参见 CleanCode:37ff)。假设您的客户要求您添加 persistToXml()
方法。您现在不仅必须更改 Registry 类以添加另一个方法,而且还必须更改客户端以适应该新功能。这是您必须更改的两个类,当 OCP 告诉我们应该关闭我们的类以进行修改时。
一种改进方法是在注册表上添加一个通用的 persist()
方法并将开关/案例移入其中,这样客户端只需要调用
$registry->persist();
这样更好,但它仍然留给我们 switch/case,并且它仍然迫使我们在每次添加新的持久化方法时修改注册表。
现在再假设您的产品是许多开发人员使用的框架,他们提出了自己的持久化算法。他们如何添加它们?他们必须扩展你的类,但他们也必须替换框架中使用你的类的所有事件。或者他们只是将它们写入您的类(class),但每次您提供新版本时他们都必须修补类(class)。所以这就是一堆蠕虫。
救援策略。由于持久算法是变化的东西,我们将封装它们。由于您已经知道如何定义一系列算法,因此我将跳过该部分,仅展示生成的客户端:
class Registry
{
public function persist()
{
$this->persistable->persist($this->data);
}
public function setPersistable(Persistable $persistable)
{
$this->persistable = $persistable
}
// other code …
很好,我们refactored the conditional with polymorphism .现在您和所有其他开发人员可以将任何 Persistable 设置为所需的策略:
$registry->setPersistable(new PersistToCloudStorage);
就是这样。没有更多的开关/外壳。不再有注册表黑客攻击。只需创建一个新类并进行设置即可。该策略让算法独立于使用它的客户端而变化。
另见
[GoF] Gamma, E.、Helm, R.、Johnson, R.、Vlissides, J.,设计模式:可重用面向对象软件的元素,马萨诸塞州雷丁:AddisonWesley,1995 年。
[CleanCode] Martin, Robert C. Clean Code:敏捷软件工艺手册。新泽西州上马鞍河:Prentice Hall,2009 年。打印。
关于php - 在php中使用策略模式的优点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17721623/
下面我有一段代码可以在我的大多数简单程序中运行.. . 我想知道它是好是坏……以及利弊。 . win32头文件:win32.h // example of a not realated code to
了解到我们可以使用双括号初始化在 java 中初始化集合。并对其进行了一些搜索,发现由于其性能问题,不建议使用它。 private static final Set VALID_CODES = new
在 Java 中使枚举类似于类,而不是像 C/C++ 中的常量集合,有哪些优点? 最佳答案 您可以免费在编译时检查有效值。使用 public static int OPTION_ONE = 0; pu
我目前正在研究ruleML,我想知道是否有人可以给我列出一些优缺点? 谢谢 最佳答案 RuleML是语义网现有本体语言和查询系统的概括,例如OWL-DL,围绕RDF的工具集以及基于一阶逻辑的类似于Pr
每次我写某种形式的东西 let scorePopulation f population = Array.map (fun i -> f i) population 我最后问自己,我是否会写得更好
我总是从SQL专家那里听到,在SELECT语句中使用'*'符号效率不高,最好列出所有字段名称。 但是,对于将新字段添加到表然后相应地更新所有存储过程的情况下,我个人觉得效率不高。 那么使用'*'的优缺
我想知道通过将业务逻辑和数据与 Web 表单分离来分层 Web 应用程序的长期优势(如果有)。 (即表单、业务逻辑、数据不在同一个文件中,但每个都在另一个文件夹中的自己的类中,或者与其他类似的类组合)
我目前正在从事一个项目,其中分支和合并从一开始就运行得不太好。为了改变这一点,我们一直在讨论多种不同的方法。我想每个人对于如何做这类事情都有自己的哲学,所以它似乎也在这里。 我们一直在讨论的一件事是按
是 StyleCop好用,有什么优缺点? 我还下载了 StyleCop,Resharper StyleCop。 我正在使用 resharper,它有自己的编码标准,而 StyleCop 也有自己的,我
我刚刚开始学习C#,并使用Tutorials Point来完成此操作。在数组部分,我一直看到声明为 string[] sarray = { "Hello", "From", "Tutorials",
使 Java 中的枚举类似于类,而不是像 C/C++ 中那样只是常量的集合有哪些优势? 最佳答案 您可以获得有效值的免费编译时检查。使用 public static int OPTION_ONE =
您会在什么情况下使用 volatile 关键字?更重要的是:该计划如何从中受益? 根据我已经阅读和了解的内容:volatile 应该用于被不同线程访问的变量,因为它们比非 volatile 变量读取起
至少有三种众所周知的创建并发应用程序的方法: 通过锁定(.NET、Java)实现多线程和内存同步。软件事务内存 (link text) 是另一种同步方法。 异步消息传递(Erlang)。 我想了解是否
在对JCR or RDBMS进行了一些研究并阅读了其他posts之后,我仍然不确定是否将JCR over JPA用于文档管理系统,该系统必须处理不同的文档类型,非常大的文件和并发访问很多来自许多用户。
X 来自 http://drupal.org/node/953016 的帖子 Drupal 7 AJAX 系统很棒,它对表单甚至链接都非常流畅。 我无法以理智的方式解决方法是从 javascript
我的 .htaccess 中有一堆规则(子域、文件夹、用户特定的文件夹等...) 我现在正在使用这个正则表达式: ([a-z0-9A-Z]) 我正在寻找一个特定的规则,我找到了多种构建它的方法,我想知
好吧,我想这很清楚我试图对此进行推理的方向。 这些天有很多关于不变性(constness)的优点的讨论。 Java 中的并发编程一书也对此进行了很多讨论。 然而,这一切只是我所读到的。我个人没有用函数
我正在开发一个 Android 应用程序,但我遇到了一个无法以某种方式做出决定的决定。我希望有人能够阐明常见的做法以及支持它们的任何理论。 问题是这样的: 我想要一个包含图像和文本(例如表格)的项目列
是否可以使用 ≠ 而不是 !=。我知道这是一个额外的 alt 代码,我从未在项目中使用过它,但我已经对其进行了测试并且可以正常工作。除了必须 Alt +8800 之外还有什么优点/缺点吗? 编辑:我不
Visual Studio (sqlmetal) 生成的 dbml 文件带有映射到数据库表的实体。在您看来,这些类适合用作领域模型类吗?还是应该避免它们,只将它们隔离到数据访问层? 谢谢 最佳答案 在
我是一名优秀的程序员,十分优秀!