首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我们称之为这种设计模式,它与战略模式是一样的?

我们称之为这种设计模式,它与战略模式是一样的?
EN

Software Engineering用户
提问于 2021-10-21 18:14:17
回答 3查看 706关注 0票数 2
代码语言:javascript
复制
abstract class BaseService {
 public void doSomething();
}  


class AService extends BaseService {
  public void doSomething(){
   // Do something...
  }
}

class BService extends BaseService {
  public void doSomething(){
   // Do something...
  }
}

class ServiceResolver {
 pubic static BaseService resolveService(String type) {
  if(type == "A") return new AService();
  if (type == "B") return new BService();
 }
}

Usage:
BaseService resolvedService = ServiceResolver.resolveService(type);
resolvedService.doSomething();

我们把上面的模式叫做什么?这是否与战略模式相同?我觉得这是不同的,因为在策略模式中,客户端选择算法类型(https://refactoring.guru/design-patterns/strategy)并将其传递给上下文类执行,并在运行时更改对象的行为(上下文类对象),但在我的上面示例中,我们没有做任何这样的事情。

此外,在扩展上述代码时:

代码语言:javascript
复制
class ServiceResolver {

@Autowired
AService aService;

@Autowired
BService bService;

 pubic static BaseService resolveService(String type) {
  if(type == "A") return aService;
  if (type == "B") return bService;
 }
}

从总体上看,它和第一个看起来是一样的。

EN

回答 3

Software Engineering用户

发布于 2021-10-21 18:30:42

我最初称这为工厂方法模式,但正如菲利普所指出的,这是不正确的。它实际上只是一个充当对象工厂的方法。我明白为什么您可能认为它与策略模式相关,但是在策略中,底层实现对象的更改是在策略对象中完成的。在这种情况下,意图是不同的,因为您正在创建这些对象,并将它们交给系统的其他部分来管理。

您在这里所做的事情是一种有用而简单的方法,可以消除对具体类及其构造函数的显式依赖。如果它满足了您的需要,我认为没有理由通过实现更正式的Factory方法模式来使事情变得过于复杂。

票数 3
EN

Software Engineering用户

发布于 2021-10-21 20:26:26

就其本身而言,这只是一个多态应用程序,但您也可以将其看作是一个不完整的策略模式,添加了几个附加元素:

代码语言:javascript
复制
// abstract strategy type
abstract class BaseService { 
  public void doSomething();
}  


// concrete strategy A
class AService extends BaseService {
  public void doSomething(){
    ...
  }
}

// concrete strategy B
class BService extends BaseService {
  public void doSomething(){
    ...
  }
}

// A factory (not an Abstract Factory, not a Factory Method)
// acting as a Service Locator ("service resolver" basically means the same thing)
class ServiceResolver {
 pubic static BaseService resolveService(String type) {
  if(type == "A") return new AService();
  if (type == "B") return new BService();
 }
}

工厂只是一些可以创建其他对象的函数(或对象);它基本上是构造函数的一个更复杂的替代(它是一个“美化的构造函数”)。

抽象工厂工厂法模式是专门的工厂类型,旨在解决更多与创建相关的特殊类型的问题。人们有时会称一个简单的工厂为一个函数,一个工厂函数或一个工厂方法,但这是不同的。

服务定位器是一个全局(或相当全局的)对象,您可以请求依赖项;它通常被认为是反模式(而不是显式依赖注入),主要是因为它的全局性质(您可以在任何地方调用它(或多或少),也因为它使依赖关系隐式(依赖关系没有反映在构造函数或接口中)。

“几乎-策略”中缺少的是一个显式的上下文对象:

代码语言:javascript
复制
// This is the code that selects the strategy. 
// So, it could be seen as the client (or a part of it). 
// It doesn't matter that it delegates the job to the service locator
BaseService resolvedService = ServiceResolver.resolveService(type);

// This is the "guts" (what would be the internal details) of your nonexistent Context
resolvedService.doSomething();

现在,战略模式的全部思想是,您可以创建这些预先配置的上下文实例,并将它们作为对象传递。而且有时可能会动态地改变他们使用的策略(或者不是,您可以任意设计)。

所以,就像:

代码语言:javascript
复制
// The Context
class Doer {
  pubic void doTheThing() {
     /* some higher-level logic/algorithm */
     // step 1
     // step 2
     // ...

     // step i - varies - delegate to the strategy:
     this.resolvedService.doSomething();
     
     // ...
     // step N
  }

  // maybe some other methods...
}

// -----------------------------
// In the client:
Doer doer = new Doer(ServiceResolver.resolveService(type));

// call it or send it on its way

如果您的客户端和/或上下文非常简单,或者即使不是,但您还没有认识到它是它自己的单独的东西,并且没有经历重构步骤来提取它,并使它在代码中更显化和更好地定义,那么您将不会有一个明显的上下文对象。事实上,随着开发的进展,您可能会惯性地在几个地方重复大致相同的代码,然后您才会意识到,通过使用不同的策略预先配置几个上下文实例,这些代码可能会变得干涸。

票数 1
EN

Software Engineering用户

发布于 2021-10-22 07:39:09

在您的第一个代码示例中,您有一个工厂,但它是一个有问题的工厂。它是一个静态方法,所以任何使用这个工厂的代码都会紧密耦合到这个实现中。其次,该方法本身与具体实现紧密耦合:AServiceBService。所有这些紧密耦合使得测试这些代码非常困难。静态工厂是那些与反模式有关的工厂之一。如果它提供的对象是确定性的和无副作用的,那么它们是可以的,但是服务不太可能满足这个要求,因此这种方法在这里可以被看作是一个糟糕的方法。

第二个代码示例,您似乎正在注入aServicebService,这是很好的。你的工厂已经改进了。但是,您已经将这两项耦合到具体类型,AServiceBService,这很糟糕,因为依赖注入增加了复杂性,除了消除第一个示例中的"new胶水“耦合问题之外,没有提供更多的好处。你已经减少了你的耦合,但仍然有一些。不幸的是,这是货物偷盗的一个例子。这些类型需要替换为抽象类或接口,这取决于您的语言支持。

但事情会变得很奇怪。resolveService仍然是静态的,但它访问实例成员aServicebService。我看不出这是怎么编出来的。那是个错误吗?

在您对JimmyJames的评论中,您将介绍代码AService.getInstance()。这是单例模式的一个例子。它只是一个被美化的全局变量,也是一个绝对的反模式。单例应该仅通过DI注入来处理。

票数 0
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/432908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档