• 开闭原则


    1.定义

       OCP(Open-Closed Principe):一个软件实体应该对扩展开放,对修改关闭。也就是在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即实现在不改源代码的情况下改变这个模块的行为。

    2.案例

       某图形界面系统提供了各种不同形状的按钮,客户端代码可针对这些按钮进行编程,用户可能会改变需求而使用不同的按钮,原始设计方案如下图所示:

        

    3.分析

       由于LoginForm类面向具体对象而进行编程,因此每次更换具体类时不得不修改源代码,而且这些类中方法都没有一个统一的接口,相似功能的方法名称不一致。如果系统要满足开闭原则,需要对按钮类进行抽象化,提取一个抽象类AbstructButton,LoginForm类针对抽象类AbstractButton进行编程,在Java中,可以通过配置文件、DOM解析技术和反射机制将具体类类名存储在配置文件中,再在生成时实例化其对象(后续介绍)。

       使用抽象类AbstractButton后,如果需要矩形按钮(RectangleButton),只需添加一个新的类继承抽象类并修改配置文件OCP.xml即可,无须修改LoginForm类中的代码和AbstractButton的代码,在不修改的前提下扩展系统功能的要求,完全符合开闭原则。配置文件一般都用XmL格式文件或properities格式的属性文件,如图:

      

          注:xml和properties的配置文件都是纯文本文件,可以直接通过VI编辑器或记事本进行编辑,且无需编译,因此在软件开发中,一般不把配置文件的修改认为是对系统源代码的修改。

    4.实现

       除了图中四个类,我自己写了个XMLHepler类,用来帮助LoginForm获取按钮名。

          4.1XMLHelper类的设计实现如下:

    package OCP;
    
    import java.io.IOException;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.NodeList;
    import org.xml.sax.SAXException;
    
    public class XMLHepler {
    
        //帮助loginform获取到按钮名字的类 操作xml文件
        public XMLHepler() {
            // TODO Auto-generated constructor stub
        }
        public String getButtonName()
        {
            DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();//实例化一个documentbuilderfactory 用来获取documentbuilder
            DocumentBuilder builder=null;
            try {
                builder=factory.newDocumentBuilder();
            }catch(ParserConfigurationException e)
            {
                e.printStackTrace();
            }
            Document document=null;
            try {
                document=builder.parse("OCP.xml");//从指定路径获取xml文件 这里ocp.xml在项目文件夹下
                
            }catch (SAXException e) {
                // TODO: handle exception
                e.printStackTrace();
            }catch(IOException e)
            {
                e.printStackTrace();
            }
            NodeList nList=document.getElementsByTagName("ButtonName");//节点名叫“buttonname” 获取其中的内容
            return nList.item(0).getFirstChild().getNodeValue();//返回其内容
        }
    }

          4.2LoginForm类的设计实现如下:

    package OCP;
    import java.awt.Container;
    
    import javax.swing.*;
    public class LoginForm extends JFrame{
    
        private AbstructButton button=null;
        private XMLHepler xmlHepler=null;
        public LoginForm() {
             setTitle("OCP");
             setVisible(true);
             setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
             setBounds(0,0,200,200);
             setLayout(null);//绝对布局
        }
        //面板容器添加控件
        public void showControl() throws InstantiationException, IllegalAccessException, ClassNotFoundException
        {
            xmlHepler=new XMLHepler();
            String btnName=xmlHepler.getButtonName();
            Container container=getContentPane();
            button=(AbstructButton)Class.forName(btnName).newInstance();//根据名字来实例化对应的按钮
            button.InitButton();
            container.add(button);
        }
        public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
            // TODO Auto-generated method stub
            new LoginForm().showControl();
        }
    
    }

          4.3AbstractButton类设计实现如下:

    package OCP;
    import javax.swing.*;
    public abstract class AbstructButton extends JButton {
    
        //设计抽象类 满足所有按钮的需求
        public AbstructButton() {
            // TODO Auto-generated constructor stub
        }
        public abstract void InitButton();//抽象方法没有方法体 且子类必须重写
        
    }

          4.4RectangleButton类设计实现如下:

    package OCP;
    
    import java.awt.Color;
    
    public class RectangleButton extends AbstructButton {
    
        //实际按钮一 矩形按钮
        public RectangleButton() {
            // TODO Auto-generated constructor stub
        }
        @Override
        public void InitButton()//重写父类方法 初始化一个矩形按钮
        {
            this.setText("矩形按钮");
            this.setBounds(50,50,120,40);
            this.setBackground(Color.CYAN);
        }
    
    }

          4.5CircleButton类设计实现如下:

    package OCP;
    
    import java.awt.Color;
    
    public class CircleButton extends AbstructButton{
    
        //实际按钮二 圆形按钮
        public CircleButton() {
            // TODO Auto-generated constructor stub
        }
        @Override
        public void InitButton()//重写父类方法 圆形按钮初始化
        {
            this.setText("圆形按钮");
            this.setBackground(Color.yellow);
            this.setBounds(50,50,120,40);
        }
    }

           4.6运行效果图如下:

         

      

         

                注:本人参考的书籍是清华大学出版社,刘伟主编的《设计模式》。代码中存在的不足,还请多多指教。

  • 相关阅读:
    一部感天动地的自学编码之旅
    c++初学
    imooc-c++学习感悟
    第二次实践作业
    大一下学期的自我目标(要求包含对大一上学期的总结、对面向对象课程完成后学习到的能力的预期,对面向对象课程的期望、对编程和专业能力的愿景规划)
    面向对象程序设计 ——第二次作业(2)
    面向对象程序设计 ——第二次作业(1)
    面向对象程序设计 ——第一次作业
    面对对象程序设计第二次作业2
    面对对象程序设计第二次作业
  • 原文地址:https://www.cnblogs.com/Juice-Dreamer/p/9825058.html
Copyright © 2020-2023  润新知