Log*_*gan 5 java design-patterns
我有多个服务使用一种方法实现接口 - execute()
. 每个服务都使用此方法根据字符串值执行一些操作,在原始代码中,该值是枚举,因此这些值是常量。
interface Service{
public void execute();
}
class Service1 implements Service{
//constructors
public void execute(JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
doSomething(payload);
}
}
}
class Service2 implements Service{
//constructors
public void execute(JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
doSomething1(payload);
}
if(payloadType.equals("type2")){
doSomething2(payload);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想避免每次创建新服务时都编写相同的 if 语句。问题是,每个服务不必根据每个字符串类型执行操作。所以Service1在type等于"type1"时执行action,而Service2根据"type1"和"type2"执行action。
我尝试了以下解决方案:
class Main {
public static void main(String[] args) {
exec(new B(), "type2");
}
private static void exec(Service service, JSONObject payload, String payloadType){
if(payloadType.equals("type1")){
Init i = (Init)service;
i.init(payload);
}
if(payloadType.equals("type2")){
Action a = (Action)service;
a.action(payload);
}
}
}
interface Service{
}
interface Init{
public void init(JSONObject payload);
}
interface Action{
public void action(JSONObject payload);
}
class A implements Service, Init{
@Override
public void init(JSONObject payload){
doSomething(payload);
}
}
class B implements Service, Init, Action{
@Override
public void init(JSONObject payload){
doSomething1(payload);
}
@Override
public void action(JSONObject payload){
doSomething2(payload);
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码有效,但我不喜欢使用强制转换。我认为这不是一个好习惯,也很不安全。你能建议我在这里使用什么设计模式或其他解决方案吗?我试过访问者,但我无法弄清楚这个案例的正确实现。
更新
感谢所有的答案,他们非常有帮助。我设法实现了我想要的。这是最终有效的代码。
public class Main {
public static B b = new B();
public static A a = new A();
public static void main(String[] args) {
exec(b, "init");
}
private static void exec(Service service, String type){
if(type.equals("init") && service instanceof Init){
service.fillCarrier(new InitCarrier());
}
if(type.equals("action") && service instanceof Action){
service.fillCarrier(new ActionCarrier());
}
}
}
interface Carrier<T>{
public void set(T t);
}
class InitCarrier implements Carrier<Init>{
public void set(Init init){
init.init();
}
}
class ActionCarrier implements Carrier<Action>{
public void set(Action action){
action.action();
}
}
abstract class Service{
public void fillCarrier(Carrier carrier){
carrier.set(this);
}
}
interface Init{
public void init();
}
interface Action {
public void action();
}
class A extends Service implements Init{
@Override
public void init(){
System.out.println("init a");
}
}
class B extends Service implements Init, Action{
@Override
public void init() {
System.out.println("init b");
}
@Override
public void action(){
System.out.println("action");
}
}
Run Code Online (Sandbox Code Playgroud)
棘手的问题,我可能有一个可行的解决方案。
那将是存储类型,以及类型以 HashMap 形式执行的代码。
HashMap<String, Function<Void, Void>> types = new HashMap<String, Function<Void, Void>>();
Run Code Online (Sandbox Code Playgroud)
然后在主函数中,您将使用类型名称及其运行的函数填充 HashMap。
types.put("Type1",()->{
/*Do something*/
});
types.put("Type2",()->{
/*Do something*/
});
types.put("Type3",()->{
/*Do something*/
});
Run Code Online (Sandbox Code Playgroud)
然后在服务中,您将有一个字符串数组来表示它使用的类型。例如:
String[] serviceTypes = {"Type1", "Type2"};
Run Code Online (Sandbox Code Playgroud)
最后,在服务的执行函数中,您将对字符串运行相应的 lambda。
public void execute(String type){
if((new ArrayList<>(Arrays.asList(serviceTypes))).contains(type)) {
Main.types.get(type);
}
}
Run Code Online (Sandbox Code Playgroud)