【问题标题】:Java Design Patterns QuizJava 设计模式测验
【发布时间】:2016-08-11 06:05:18
【问题描述】:

最近我遇到了一个问题,我被要求使用适当的设计模式进行设计。问题陈述是:

Implement a remote control of TV. 
Any remote control we use, either at home/hotel or at a friend’s place, 
we just pick up the TV remote control and start pressing Up and Down 
or Forward and Back keys to change the channels.
Choose a suitable design pattern for implementation of this problem.

我不知道如何设计这个问题。这是我想出的:

Place 是一个抽象类。

家延伸地方

酒店扩展了地方

FriendPlace 扩展了 Place

TVRemote 是一个类

这个地方有一个 TVRemote

键是一个接口

Keys 有一个方法 press()

UpKey、DownKey、ForwardKey、BackKey 是实现 Keys 的类

TVRemote 有键

TVRemote 中可能有更多键

这是我能想到的,但无法在此处合并设计模式。有什么指导吗?

【问题讨论】:

  • 设计会怎样?
  • 我认为地点无关紧要,因为电视和遥控器之间的交互完全独立于地点。

标签: java algorithm oop design-patterns


【解决方案1】:

一个简单的方法是创建一个界面

interface RemoteControl 
{
public void up(); 
public vois down();
public void forward();
public void back();
} 

然后创建为特定设备实现该接口的特定类

例如

public class HomeRemote implements RemoteControl {

public void up(){
..
} 

public vois down(){
..
}

public void forward(){
..
}

public void back(){
..
}

}

然而

经过我们的讨论 - 在搜索了更多之后,我现在倾向于认为 Bridge 模式是这里所要求的。 看看这个 - http://www.programcreek.com/2011/10/java-design-pattern-bridge/

远程控制的抽象类与(上、下、前进、后退)的基本实现一起使用 然后每个特定的 TVRemote 扩展抽象类以添加更多/和设备特定的功能。

另请注意,电视使用的是通用接口,其中描述了 (goUp()、goDown()、goForward()、goBack() 和可能的 on()、off()) 函数。

【讨论】:

  • 当他们只有 4 个命令并与同一设备电视交互时,家庭遥控器与朋友的地方遥控器有何不同?
  • 这些设备实际上是不同的——如果我在家里说 LG 而你有三星或其他什么——它们的设计方式完全不同。您所指的 4 个命令是通用接口 - 但每个设备的实现方式不同(在低级别)。最终用户并不关心实际的实现——他/她只是使用接口,
  • 对。最终用户不必担心实现,但我觉得所有命令都具有相同的功能,尽管必须使用不同型号的设备。向上键只执行向上,与向下和向前和向后相同。我想不需要单独的远程实现。遥控器有一个键,当你按下() UpKey 时,它会执行操作。
  • 好的。所以我们不同意这一点;-) 实际上,“向上”可以以不同的方式实现——如果你考虑到接收到的信号是如何在内部处理的等等——它与用户的“感觉”相同是无关紧要的。因此,我很清楚他们要求您使用接口。另请注意,问题要求您实施电视遥控器。所以我认为在你的答案中描述地点等是无关紧要的。
  • 地点,我同意无关紧要。我们可以丢弃它。关于命令功能,Back 和 Forward 用于更改频道,Up 和 Down 用于更改音量。所以所有遥控器的功能都是一样的。
【解决方案2】:

一些观察:

  • 不同的遥控器可能有不同数量的按钮
  • 不同的按钮执行不同的操作
  • 远程控制应该忽略操作执行的细节
  • 应该能够通过为按钮分配不同的操作或支持不同的设备来重新编程遥控器

在这种情况下使用最直接的模式是Command。可以创建特定的Command 实现,然后将Commands 分配给按钮:

public interface Command {
    void Execute();
}
public class Button {
    private readonly Command command;
    public Button(Command command) {
        this.command = command;
    }
    public void Press() {
        this.command.Execute();
    }
 }
 public class Remote {
     public Button ButtonPlaceholder1 { get; set; }
     public Button ButtonPlaceholder2 { get; set; }
     public Button ButtonPlaceholder3 { get; set; }
     public Button ButtonPlaceholder4 { get; set; }
 }

那么,拥有Button 课程有什么好处?好吧,假设您要引入一个可以上下移动的滑块按钮。在这种情况下,您将使用两个Commands 对其进行配置:

public class SliderButton {
    public SliderButton(Command up, Command down) {
        this.commandUp = up;
        this.commandDown = down;
    }
    public void Up() {
        this.commandUp.Execute();
    }
    public void Down() {
        this.commandDown.Execute();
    }
}

关于这次采访的有趣的后续问题是,“如何实现一个按钮来取消按下前一个按钮所做的动作?(例如,我正在观看 ESPN 频道,但在比赛之间有一个休息时间,所以我切换到MTV,但我想偶尔检查一下break是否结束,如果没有,请返回MTV)

【讨论】:

    【解决方案3】:

    你应该在这里使用command 模式。通常它有 Invoker、Client、Command 和 Receiver。以下是您可能需要的课程。

    命令

    public interface ICommand {
        void execute();
    }
    

    调用者

    public class RemoteControl {
        Map<Key, ICommand> commandsByKey;
    
        public RemoteControl() {
            commandsByKey = new HashMap<>();
        }
    
        public void setCommand(Key key, ICommand command) {
            commandsByKey.put(key, command);
        }
    
        public void press(Key key) throws Exception {
            ICommand command = commandsByKey.get(key);
            if(command == null)
                throw new Exception("Invalid Key");
            command.execute();
        }
    }
    

    接收者

    public class TV {
        private String brand;
    
        public TV(String brand) {
            this.brand = brand;
        }
    
        @Override
        public String toString() {
            return brand + " TV";
        }
    }
    

    客户

    public abstract class Place {
        private TV tv;
        private RemoteControl remoteControl;
    
        public Place(TV tv) {
            this.tv = tv;
            this.remoteControl = new RemoteControl();
    
            remoteControl.setCommand(Key.UP, new UpCommand(this.tv));
            remoteControl.setCommand(Key.FORWARD, new ForwardCommand(this.tv));
            remoteControl.setCommand(Key.DOWN, new DownCommand(this.tv));
            remoteControl.setCommand(Key.BACK, new BackCommand(this.tv));
        }
    
        public TV getTv() {
            return tv;
        }
    
        public RemoteControl getRemoteControl() {
            return remoteControl;
        }
    }
    
    public class Home extends Place {
        public Home() {
            super(new TV("Sony"));
        }
    }
    
    public class Hotel extends Place {
    
        public Hotel() {
            super(new TV("LG"));
        }
    }
    

    具体命令

    public class UpCommand implements ICommand {
        private TV tv;
    
        public UpCommand(TV tv) {
            this.tv = tv;
        }
    
        @Override
        public void execute() {
            System.out.println("Up Command  - " + tv);
        }
    
    }
    
    
    public class DownCommand implements ICommand {
        private TV tv;
    
        public DownCommand(TV tv) {
            this.tv = tv;
        }
    
        @Override
        public void execute() {
            System.out.println("Down Command  - " + tv);
        }
    }
    
    
    public class ForwardCommand implements ICommand {
        private TV tv;
    
        public ForwardCommand(TV tv) {
            this.tv = tv;
        }
        @Override
        public void execute() {
            System.out.println("Forward Command  - " + tv);
    
        }
    
    }
    
    
    public class BackCommand implements ICommand {
        private TV tv;
    
        public BackCommand(TV tv) {
            this.tv = tv;
        }
    
        @Override
        public void execute() {
            System.out.println("Back Command  - " + tv);
        }
    
    }
    

    按键

    public enum Key {
        UP, DOWN, FORWARD, BACK
    }
    

    测试

    public class RemoteTest {
        public static void main(String[] args) throws Exception {
            Place home = new Home();
            home.getRemoteControl().press(Key.UP);
            home.getRemoteControl().press(Key.DOWN);
            home.getRemoteControl().press(Key.BACK);
    
            Hotel hotel = new Hotel();
            hotel.getRemoteControl().press(Key.UP);
        }
    }
    

    如果您向遥控器添加任何其他键,则无需触摸任何现有命令或调用程序。您只需要在客户端中添加它。这遵守Open Close principle。如果每个地方都有不同的遥控器,则将其作为构造函数参数,因此您无需更改任何其他类。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-14
      相关资源
      最近更新 更多