首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >命令模式实现

命令模式实现
EN

Code Review用户
提问于 2014-05-30 18:35:41
回答 2查看 602关注 0票数 0

最近,我已经熟悉了命令模式的实现。我遇到了一个问题,我需要为用户选择执行哪种方法来执行输入方法名称或编号,这与这个具体的方法执行有关。如果我不需要为每个方法创建单独的类,一切都会好的,如下所述:

代码语言:javascript
复制
public interface Order {
    void execute ();
}

// Receiver class.
class StockTrade {
    public void buy() {
        System.out.println("You want to buy stocks");
    }
    public void sell() {
        System.out.println("You want to sell stocks ");
    }
}

// Invoker.
class Agent {

    void placeOrder(Order order) {
        order.execute();
    }    
}

//ConcreteCommand Class.
class BuyStockOrder implements Order {

    private StockTrade stock;

    public BuyStockOrder(StockTrade st) {
        stock = st;
    }
    public void execute() {
        stock.buy();
    }
}

//ConcreteCommand Class.
class SellStockOrder implements Order { 
    private StockTrade stock;
    public SellStockOrder (StockTrade st) {
        stock = st;
    }
    public void execute() {
        stock.sell();
    }
}

// Client
public class Client {
    public static void main(String[] args) {
        StockTrade stock = new StockTrade();
        BuyStockOrder buyStockOrder = new BuyStockOrder(stock);
        SellStockOrder sellStockOrder = new SellStockOrder(stock);
        Agent agent = new Agent();

        agent.placeOrder(buyStockOrder ); // Buy Shares
        agent.placeOrder(sellStockOrder ); // Sell Shares
    }
}

如何避免为每个方法创建过多的类,这些方法也将是正确和灵活的?

EN

回答 2

Code Review用户

发布于 2014-05-30 18:51:47

我可能无法回顾您具体要求的要点,但我将进行一般性回顾:

  1. 从接口中省略publicabstract关键字,它是隐式的。
  2. 保持语法间距一致。例如,您有public abstract void execute ( );,而应该是void execute();,程序中的某些字符串也可能有固定的间距。
  3. 不要使用m_启动实例变量,也许这是另一种背景下的常见实践,但在Java中并非如此。不过,您似乎在其他地方坚持使用camelCasing。
  4. 在可能的情况下使参数final。如果不小心更改原语或对对象的引用,则会产生编译器错误。
  5. 使用泛型,在Agent中您将m_ordersQueue指定为new ArrayList(),您希望使用泛型。如果可以存储所有类型的对象,则使用new ArrayList<Object>()。我看到您忘记声明变量的类型,使用Java7‘S钻石操作符,它将是private final List<Object> ordersQueue = new ArrayList<>();,还注意到我只将List<Object>定义为类型,因为如果可能的话,您总是希望使用接口来声明类型。
  6. 给变量起名,bscssc不是描述性的。
  7. 最后,我会考虑对Queue<Object>中的ordersQueue使用Agent,这个名称意味着您想要一个队列实现,但是您使用的是list实现。

好消息是,您似乎正确地遵循了一些范例,并且相当合理地理解了OOP,但是您确实需要在某些方面进行改进。

票数 3
EN

Code Review用户

发布于 2014-05-30 19:01:20

我会继续到@skiwi停下来的地方。关于你的具体问题,有几种选择。

但是@skiwi没有提到的一点是,您应该用@Override标记所有可能的方法

一种方法是使用布尔值,但由于很容易混淆真假,所以我认为枚举更好:

代码语言:javascript
复制
public enum BuyOrSell { BUY, SELL; }

class BuyOrSellStockOrder implements Order {
    private final StockTrade stock;
    public BuyOrSellStockOrder(StockTrade st, BuyOrSell action) {
        this.stock = st;
        this.action = action;
    }

    @Override
    public void execute() {
        if (action == BUY)
            stock.buy();
        if (action == SELL)
            stock.sell();
    }
}

但是,考虑到买卖之间的巨大差异,我认为您应该考虑为此设置两个不同的命令类。而且,如果您开始将不同的命令组合到同一个类中,它将变得非常混乱。

如果您使用的是Java 8,您可以使用如下命令:

代码语言:javascript
复制
class MyCommand implements Order {
    private final Runnable action;

    public MyCommand(Runnable action) {
         this.action = action;
    }

    @Override
    public void execute() {
         action.run();
    }
}

然后您可以创建这样的命令:

代码语言:javascript
复制
    MyCommand bsc = new MyCommand(stock::buy);
    MyCommand ssc = new MyCommand(stock::sell);

但是,虽然Java 8很漂亮,很不错,但我不确定是否推荐使用这样的命令模式。我认为通过使用方法引用,命令模式失去了一点意义。

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

https://codereview.stackexchange.com/questions/52110

复制
相关文章

相似问题

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