
下面都是伪代码,大家不必纠结于具体细节,理解意思即可。我们需要提供给上游这样一个接口, type 是指当前服务能够处理的类型,something 代表实际执行的业务功能。
public interface SomeInterface {
String type();
ResultDTO something(Param param);
}public class AImpl implements SomeInterface {
@Override
public String type() {
return "A";
}
@Override
public ResultDTO something(Param param) {
// 特有逻辑
ResultDTO resultDTO = buildPart(param);
// 构造公共逻辑所需的参数
OtherParam otherParam = new OtherParam();
// 公有逻辑
return SomeUtils.fillCommon(resultDTO, otherParam);
}
private ResultDTO buildPart(Param param) {
ResultDTO result = new ResultDTO();
// 执行查询
// 塞入特有属性
return result;
}
}public class BImpl implements SomeInterface {
@Override
public String type() {
return "B";
}
@Override
public ResultDTO something(Param param) {
// 特有逻辑
ResultDTO resultDTO = buildPart(param);
// 构造公共逻辑所需的参数
OtherParam otherParam = new OtherParam();
// 公有逻辑
return SomeUtils.fillCommon(resultDTO, otherParam);
}
private ResultDTO buildPart(Param param) {
ResultDTO result = new ResultDTO();
// 执行查询
// 塞入特有属性
return result;
}
}Map<String,SomeInterface> type2BeanMap ,然后根据当前的 type 去执行具体的实现 Bean。具体可参考《巧用 Spring 自动注入实现策略模式升级版》问题:如果我们新增 CImpl 继承 SomeInterface 就必须查看 AImpl 或者 BImpl 源码才知道有一段公共逻辑,很容易遗漏这一段公共逻辑。如果我们想让新建子类时,不需要担心遗漏这段公共的逻辑,该怎么办?public interface SomeInterface {
String type();
// 目标方法
default ResultDTO something(Param param) {
return SomeUtils.fillCommon(buildPart(param));
}
/**
* 特有逻辑
*/
MiddleParam buildPart(Param param);
}SomeInterface 改为抽象类(AbstractSomeService),something定义为 public ,将 builPart 定义为抽象函数,让子类去重写。public abstract class AbstractSomeService {
abstract String type();
// 目标方法
public ResultDTO something(Param param) {
return SomeUtils.fillCommon(buildPart(param));
}
/**
* 特有逻辑
*/
abstract MiddleParam buildPart(Param param);
}buildPart 重写的访问修饰符范围降低,如改为 protected。注意:定义中间参数:
(1) 本案例里的 SomeUtils.fillCommon 只是伪代码,公共逻辑可能封装在工具类中,也可能封装在某个 bean 中,在抽象类或者接口中可以通过ApplicationContextHolder 去获取并调用。
(2) 实际编码时,公共逻辑也未必在最后调用。
(3) 实际编码中,公共的步骤可能不止一个,但是方案是一致的,有几个定义几个抽象方法即可。
(4)实际编码时,公共的步骤可能不需要返回值
@Data
public class MiddleParam {
private ResultDTO semiResult;
private OtherParam otherParam;
}public class AImpl extends AbstractSomeService {
@Override
public String type() {
return "A";
}
@Override
protected MiddleParam buildPart(Param param) {
MiddleParam middleParam = new MiddleParam();
// 执行查询
// 塞入特有属性
return middleParam;
}
}public class BImpl extends AbstractSomeService {
@Override
public String type() {
return "B";
}
@Override
protected MiddleParam buildPart(Param param) {
MiddleParam middleParam = new MiddleParam();
// 执行查询
// 塞入特有属性
return middleParam;
}
}buildPart 这种函数名,可以明确感知到当前是对部分逻辑进行处理,且不需要在当前子类中执行公共逻辑的调用。创作不易,如果本文对你有帮助,欢迎点赞、收藏加关注,你的支持和鼓励,是我创作的最大动力。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc