【问题标题】:Factory Pattern or Extended Method?工厂模式还是扩展方法?
【发布时间】:2017-06-22 22:13:22
【问题描述】:

我正在学习设计模式,但我不确定什么是更好的做法:

我有一个“类别”类,它有几个字段:名称、2 种 url、相关对象列表。有一个方法 'toHtml()' 基本上从该类的实例生成一些 HTML。

有 4 种不同类型的 'Categories' 具有完全相同的字段,但 'toHtml()' 方法应该为每种类型提供不同的结果。

我不确定是否应该传递参数“type”和一系列 ifs/switch 语句来生成不同的 html,或者我应该将 Category 类抽象化并创建几个覆盖 toHtml() 方法的子类,然后使用 CategoryFactory 类来生成它们?在这两种情况下,我都需要传递“类型”参数。

我试图考虑“关闭以进行修改,打开以进行扩展”OOP 规则。但在这种情况下,如果我想添加“第五”类别类型,这会生成不同的 html - 对于第一个解决方案,我只需要修改 toHtml 方法(如果再添加一个),对于第二个解决方案,我需要创建额外的子类和修改 CategoryFactory 类。

什么是更好的做法?当我遇到类似的困境时,我应该遵循什么额外的规则吗?

【问题讨论】:

  • 我会将类别类抽象化,为每种类型扩展它,并让您的每种类型都有自己的 toHTML()。我建议不要在您的抽象类中创建默认 toHTML() 并强制这些类实现自己的。
  • 非常感谢@RAZ_Muh_Taz 的建议!

标签: java oop design-patterns coding-style apex


【解决方案1】:

首先,我相信您指的是工厂方法,而不是抽象工厂模式。

主要区别在于,前者为单个产品定义通用模板,而后者为一系列产品定义模板。更多信息,您可以查看here

在您的情况下,您希望为Category 定义一个模板。在此假设下,您的类组如下所示:

abstract class Category {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    abstract void toHtml();
}

class Category1 extends Category {
    public override void toHtml() {
        ... // do something here
    }
} 

class Category2 extends Category {
    public override void toHtml() {
        ... // do something else here
    }
} 

确实,这肯定有很多代码,并且可以很容易地表示为:

class Category {
    public void toHtml(Integer param) {
        if(param == 1) { // do something for Category1
        }
        else { // do something for Category2
        }
    }

归根结底,这确实是一个设计决策。您可以考虑一些因素。这会是一个不断变化的课程吗?这将被声明为全局供客户使用吗?您希望客户如何使用它?

在这一点上,更容易的事情是走阻力最小的道路。拥有一个服务所有类别的类肯定会导致更少的代码,而在 Salesforce 中,更少的代码总是一件更好的事情。但是请考虑一下:将您的功能抽象到单独的类中可以使代码更易于维护。您可能会发现编写一个类和一堵 if 语句的墙更容易,但是明天当您不在并且出现严重故障并且有人必须查看您的代码以确定究竟是哪个 if 导致了问题时,他们会因此而诅咒你。

请记住,继承是一种全有或全无的机制。如果您有一些通用功能,您可能会发现使用它特别有用,在这种情况下,您可以选择将其抽象到父类中并让您的孩子处理细节。

【讨论】:

  • 非常感谢您的详尽回答。你一直很有帮助。 :)
  • @x1r15:来自科幻背景,我知道你正在经历什么,因为我以前遇到过同样的情况。在一天结束的时候,我决定硬着头皮写那些额外的课程,从那以后它就没有伤害到我。 :) 干杯。
【解决方案2】:

如果创建Category的子类并重写toHtml()方法,为什么需要有工厂模式。如果使用引用调用运行时解析类的 toHtml() 方法,则将调用它。这意味着如果您添加一个新的 Category 子类,那么您将覆盖 toHtml () 方法,它应该可以正常工作。

【讨论】:

  • 不同的子类会在不同的地方被实例化。因此,我尽量避免直接创建它们,因为这意味着在我需要创建对象的每个地方都做出“相同的决定”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
相关资源
最近更新 更多