工厂模式还是扩展方法?

Factory Pattern or Extended Method?

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

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

有 4 种不同类型的 'Categories',它们具有完全相同的字段,但是 'toHtml()' 方法应该为每一种给出不同的结果。

我不确定我是否应该传递一个参数 "type" 和一系列 ifs/switch 语句来生成不同的 html 或者我应该制作一个类别 class 抽象和创建几个重写 toHtml() 方法的子 classes,然后使用 CategoryFactory class 生成它们?在这两种情况下,我都需要传递 'type' 参数。

我试着思考 'Close for modification, open for extension' OOP 规则。但是在这种情况下,如果我想添加 'fifth' 类别类型,它会生成不同的 html - 对于第一个解决方案,我只需要修改 toHtml 方法(如果需要再添加一个),对于第二个解决方案,我需要创建额外的子 class 并修改 CategoryFactory class。

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

如果创建一个Category的子class,重写toHtml()方法,为什么还要有工厂模式。 resolved class 运行时的 toHtml() 方法,如果使用引用调用,会被调用。这意味着如果你添加一个新的 Category subclass 然后你覆盖 toHtml () 方法并且它应该工作正常。

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

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

在您的例子中,您希望为 Category 定义一个模板。有了这个假设,这就是你的 classes 组的样子:

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
        }
    }

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

此时更容易的事情是选择阻力最小的路径。拥有一个 class 来为所有类别提供服务肯定会导致更少的代码,而在 Salesforce 中,更少的代码总是一件更好的事情。但考虑一下:将您的功能抽象为单独的 classes 可以使代码更易于维护。你可能会发现写一个 class 和一大堆 if 语句更容易,但是明天当你不在的时候出现了严重的故障,有人必须查看你的代码才能准确地找出是哪个if 造成了问题,他们会因此诅咒你。

请记住,继承是一种全有或全无的机制。如果您有一些通用功能,您可能会发现它特别有用,在这种情况下,您可以选择将其抽象为 parent class 并让 children 处理具体细节.