• 两种设计模式的结合案例


     

    摘要

    本学期我学习了“设计模式-可复用面向对象软件的基础”这门课程,这次我采用的是命令模式+策略模式两种设计模式结合的案例。

    分析的案例为:遥控器控制天花板上的吊扇,它有多种转动速度,当然也允许被关闭。假设吊扇速度:高、中、低 、关闭。采用安全模式+策略设计模式。

    报告整体结构为:两种设计模式的分析、理解,类图,实例分析、代码分析,总结。

    目录

    第一章 命令模式+策略模式 1

    1.1 命令模式 1

    1.1.1 定义 1

    1.1.2 命令模式的结构 1

    1.1.3 角色 1

    1.1.4 优点 2

    1.1.5 缺点 2

    1.1.6 适用情况 2

    1.2 策略模式 2

    1.2.1意图 2

    1.2.2 主要解决问题 2

    1.2.4 如何解决 3

    1.2.5 关键代码 3

    1.2.6优点 3

    1.2.7 缺点 3

    1.2.8 使用场景 3

    1.2.9 注意事项 3

    第二章 案例分析 4

    2.1 类图 4

    2.2 测试分析 4

    2.3 代码分析 5

    2.3.1 命令模式模块代码 6

    2.3.2 策略模式模块代码 9

    第三章 总结 12

     

    第一章  命令模式+策略模式

    本案例用到的两种案例为安全模式+策略模式,因此在分析案例之前我先对两种设计模式进行分析。命令模式具体实现命令调控,策略模式定义一系列的算法,把它们一个个封装起来。

    1.1 命令模式

    1.1.1 定义

    将来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化。用于行为请求者行为实现者解耦,可实现二者之间的松耦合,以便适应变化。分离变化与不变的因素。

    1.1.2 命令模式的结构

     命令模式是对命令的封装。命令模式把发出命令的责任和执行命令的责任分割开,委派给不同的对象。

     每一个命令都是一个操作:请求的一方发出请求要求执行一个操作;接收的一方收到请求,并执行操作。命令模式允许请求的一方和接收的一方独立开来,使得请求的一方不必知道接收请求的一方的接口,更不必知道请求是怎么被接收,以及操作是否被执行、何时被执行,以及是怎么被执行的。

    1.1.3 角色

    Command

    定义命令的接口,声明执行的方法。

    ConcreteCommand

    命令接口实现对象,是的实现;通常会持有接收者,并调用接收者的功能来完成命令要执行的操作。

    Receiver

    接收者,真正执行命令的对象。任何类都可能成为一个接收者,只要它能够实现命令要求实现的相应功能。

    Invoker

    要求命令对象执行请求,通常会持有命令对象,可以持有很多的命令对象。这个是客户端真正触发命令并要求命令执行相应操作的地方,也就是说相当于使用命令对象的入口。

    Client

    创建具体的命令对象,并且设置命令对象的接收者。注意这个不是我们常规意义上的客户端,而是在组装命令对象和接收者,或许,把这个Client称为装配者会更好理解,因为真正使用命令的客户端是从Invoker来触发执行。

    1.1.4 优点

    1.降低对象之间的耦合度。

    2.新的命令可以很容易地加入到系统中。

    3.可以比较容易地设计一个组合命令。

    4.调用同一方法实现不同的功能

    1.1.5 缺点

    使用命令模式可能会导致某些系统有过多的具体命令类。因为针对每一个命令都需要设计一个具体命令类,因此某些系统可能需要大量具体命令类,这将影响命令模式的使用。

    1.1.6 适用情况

    1.系统需要将请求调用者和请求接收者解耦,使得调用者和接收者不直接交互。

    2.系统需要在不同的时间指定请求、将请求排队和执行请求。

    3.系统需要支持命令的撤销(Undo)操作和恢复(Redo)操作。

    4.系统需要将一组操作组合在一起,即支持宏命令。

    1.2 策略模式

    1.2.1意图

    定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

    1.2.2 主要解决问题

    在有多种算法相似的情况下,使用 if...else 所带来的复杂和难以维护。

    1.2.3 何时使用

    一个系统有许多许多类,而区分它们的只是他们直接的行为。

    1.2.4 如何解决

    将这些算法封装成一个一个的类,任意地替换。

    1.2.5 关键代码

    实现同一个接口。

    应用实例: 1、诸葛亮的锦囊妙计,每一个锦囊就是一个策略。 2、旅行的出游方式,选择骑自行车、坐汽车,每一种旅行方式都是一个策略。 3JAVA AWT 中的 LayoutManager

    1.2.6优点

    1、算法可以自由切换。

    2、避免使用多重条件判断。

    3、扩展性良好。

    1.2.7 缺点

    1、策略类会增多。

    2、所有策略类都需要对外暴露。

    1.2.8 使用场景

    1、如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。

    2、一个系统需要动态地在几种算法中选择一种。

    3、如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。

    1.2.9 注意事项

    如果一个系统的策略多于四个,就需要考虑使用混合模式,解决策略类膨胀的问题。

    第二章  案例分析

    本文分析的案例为:遥控器控制天花板上的吊扇,它有多种转动速度,当然也允许被关闭。假设吊扇速度:高、中、低 、关闭。采用安全模式+策略设计模式。

    2.1 类图

    2.2 测试分析

    本案例运行测试如下,通过控制高档,中档,低档,三个命令来控制分扇转动的速度,如图2-12-22-3所示

     

    2-1 高档风速命令

     

    2-2 中档风速命令

     

    2-3 低档风速命令

     

    2.3 代码分析

    本案例以先以命令模式实现三个命令,再以策略模式定义算法实现,具体实现代码如下:

    2.3.1 命令模式模块代码

    1.Command 执行命令的接口

    package command;

    public interface Command {

    public String execute();

    public String undo();

    }

     

    2.NoCommand

    package command;

    public class NoCommand implements Command{

    public String undo() {

    return null;

    }

    @Override

    public String execute() {

    return null;

    }

    }

    3.RemoteLoader类 加载

    package command;

    import java.awt.Color;

    import java.awt.Container;

    import java.awt.FlowLayout;

    import java.awt.event.ActionEvent;

    import java.awt.event.ActionListener;

    import javax.swing.JButton;

    import javax.swing.JFrame;

    import javax.swing.JLabel;

    import javax.swing.JScrollBar;

    public class RemoteLoader extends JFrame implements ActionListener {

    private JButton high;

    private JButton middle;

    private JButton low;

    private JLabel text;

    public RemoteLoader() {

    super("设计模式");

    setSize(300, 200);

    setVisible(true);

    Container pane = getContentPane();

    FlowLayout flo = new FlowLayout();

    pane.setLayout(flo);

    high = new JButton("高档");

    high.addActionListener(this);

    middle = new JButton("中档");

    middle.addActionListener(this);

    text = new JLabel();

    low = new JButton("低档");

    low.addActionListener(this);

    pane.add(high);

    pane.add(middle);

    pane.add(low);

    pane.add(text);

    setContentPane(pane);

    setVisible(true);

    }

    public void actionPerformed(ActionEvent e) {

    if (e.getSource() == high) {

    high.setBackground(Color.cyan);

    Context1 context1 = new Context1(new OperationGao1());

    String executeStrategygao = context1.executeStrategy();

    System.out.println(executeStrategygao);

    text.setText(executeStrategygao);

    middle.setBackground(null);

    low.setBackground(null);

    }

    if (e.getSource() == middle) {

    middle.setBackground(Color.cyan);

    Context1 context1 = new Context1(new OperationGao1());

    context1 = new Context1(new OperationZhong1());

    String executeStrategyzhong = context1.executeStrategy();

    System.out.println(executeStrategyzhong);

    text.setText(executeStrategyzhong);

    high.setBackground(null);

    low.setBackground(null);

    }

    if (e.getSource() == low) {

    low.setBackground(Color.cyan);

    Context1 context1 = new Context1(new OperationGao1());

    context1 = new Context1(new OperationDi1());

    String executeStrategylow = context1.executeStrategy();

    System.out.println(executeStrategylow);

    text.setText(executeStrategylow);

    high.setBackground(null);

    middle.setBackground(null);

    }

    }

    }

     

    4.RemoteControl

    package command;

    public class RemoteControl {

    Command command;

    public RemoteControl () {

    Command noCommand = new NoCommand();

    command = noCommand;

    }

    public void setCommand(Command command) {

    this.command = command;

    }

    public String buttonWasPushed() {

    return command.execute();

    }

    public void undoButtonWasPushed() {

    command.undo();

    }

    }

     

    5.GaoCommand 类 高风速命令

    package command;

    public class GaoCommand implements Command {

    @Override

    public String execute() {

    // TODO Auto-generated method stub

    return "高风挡已经打开";

    }

    @Override

    public String undo() {

    // TODO Auto-generated method stub

      return "Gaocommand undo";

    }

    }

    6.ZhongCommand 类 中风速命令

    package command;

    public class ZhongCommand implements Command {

    @Override

    public String execute() {

      return  "中风挡已经打开";

    }

    @Override

    public String undo() {

    // TODO Auto-generated method stub

    return  "Zhongcommand undo";

    }

    }

    7.DiCommand 类 低风速命令

    package command;

    public class DiCommand implements Command {

    @Override

    public String execute() {

    // TODO Auto-generated method stub

           return "低风挡已经打开";

    }

    @Override

    public String undo() {

    // TODO Auto-generated method stub

    return  "Dicommand undo";

    }

    }

    2.3.2 策略模式模块代码

    1.Strategy1类 创建一个接口:

    package command;

    public interface Strategy1 {

       public String doOperation();

    }

     

    2.OperationGao1类 实现接口的高风速实体类

    package command;

    import command.Command;

    import command.GaoCommand;

    import command.RemoteControl;

    public class OperationGao1 implements Strategy1{

       @Override

       public String doOperation() {

        RemoteControl rc = new RemoteControl();

     Command gaoCommand = new GaoCommand();

     rc.setCommand(gaoCommand);

    return  rc.buttonWasPushed();

       }

    }

     

    3.OperationZhong1类 实现接口的中风速实体类

    package command;

    import command.Command;

    import command.RemoteControl;

    import command.ZhongCommand;

    public class OperationZhong1 implements Strategy1 {

    @Override

    public String doOperation() {

    // TODO Auto-generated method stub

    RemoteControl rc = new RemoteControl();

    Command zhongCommand = new ZhongCommand();

    rc.setCommand(zhongCommand);

    return rc.buttonWasPushed();

    }

    }

    3.OperationDi1类 实现接口的低风速实体类

    package command;

    import command.Command;

    import command.DiCommand;

    import command.RemoteControl;

    public class OperationDi1 implements Strategy1 {

    @Override

    public String doOperation() {

    RemoteControl rc = new RemoteControl();

    Command diCommand = new DiCommand();

    rc.setCommand(diCommand);

    return rc.buttonWasPushed();

    }

    }

     

    4.Context1

    package command;

    public class Context1 {

       private Strategy1 strategy1;

       public Context1(Strategy1 strategy1){

          this.strategy1 = strategy1;

       }

       public String executeStrategy(){

          

    return  strategy1.doOperation();

       }

    }

    第三章  总结

    首先真诚的感谢郭老师的认真讲解,同学们的热心帮助,让我学到了很多。刚开始学习设计模式的时候,感到这些模式真的非常抽象。后来随着郭老师的讲解,以及在同学们的帮助下我慢慢学会了一些设计模式,简单理解了设计模式的概念。

    在本次的作业中,我使用的是含有命令模式和策略模式的案例。经过这次的作业,不仅让我多这两种模式有了很好的理解,更重要的是我对整个设计模式都有了一定的了解。

    命令模式就是将来自客户端的请求传入一个对象,从而使你可用不同的请求对客户进行参数化。用于行为请求者行为实现者解耦,可实现二者之间的松耦合,以便适应变化。策略模式就是定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换。

    设计模式,它给出了很多设计中的技巧与思路,对于很多优秀的设计,它加以总结与提炼。设计模式并非四人团拍脑瓜想出来的,而是他们搜集了其他人优秀的设计,加以整理出来的。

    应用设计模式会给我们带来很多好处:软件将变得更加灵活,模块之间的耦合度将会降低,效率会提升,开销会减少。更重要的,设计模式就好像美声唱法中的花腔,让你的设计更加漂亮。总的来说,设计模式似乎将软件设计提升到艺术的层次。

    设计模式已经被广泛的应用了,在现在很多的图形界面框架都使用了MVC模式,大量跌代器模式的应用,彻底改变了我们对集合的操作方式。不仅如此,应用了设计模式的设计,往往被看成为优秀的设计。

    最后再一次感谢郭老师为我们讲解设计模式,郭老师也一直在和我们一起学习,一起进步,希望您身体健康,家庭幸福。

  • 相关阅读:
    Quartz使用总结(转)
    JAVA中使用LOG4J记录日志
    Java用HttpsURLConnection访问https网站的时候如何跳过SSL证书的验证?
    JAVA_HOME设置
    命令行启停mysql数据库
    本地jar包引入到maven项目中
    Could not clean server of obsolete files
    python基础一
    11-数据的增删改
    10-外键的变种 三种关系
  • 原文地址:https://www.cnblogs.com/caozong/p/5690566.html
Copyright © 2020-2023  润新知