zoukankan      html  css  js  c++  java
  • 创建型模式之抽象工厂模式

    工厂三兄弟:简单工厂模式,工厂方法模式,抽象工厂模式我选最优讲解,以后其他的设计模式都选用改良版最优模式讲解,其他的请自行百度。

    工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产,这就是我们本文将要学习的抽象工厂模式的基本思想。
     
    界面皮肤库的初始设计(案例)
    Sunny软件公司欲开发一套界面皮肤库,可以对Java桌面软件进行界面美化。为了保护版权,该皮肤库源代码不打算公开,而只向用户提供已打包为jar文件的class字节码文件。用户在使用时可以通过菜单来选择皮肤,不同的皮肤将提供视觉效果不同的按钮、文本框、组合框等界面元素,其结构示意图如图所示:
     

    完整解决方案:

    Sunny公司开发人员使用抽象工厂模式来重构界面皮肤库的设计,其基本结构如图所示:

    界面皮肤库结构图:

    在图中,SkinFactory接口充当抽象工厂,其子类SpringSkinFactory和SummerSkinFactory充当具体工厂,接口Button、TextField和ComboBox充当抽象产品,其子类SpringButton、SpringTextField、SpringComboBox和SummerButton、SummerTextField、SummerComboBox充当具体产品。完整代码如下所示:

    按钮:

    //在本实例中我们对代码进行了大量简化,实际使用时,界面组件的初始化代码较为复杂
    //按钮接口:抽象产品
    interface Button {
        public void display();
    }
    //Spring按钮类:具体产品
    class SpringButton implements Button {
         public void display() { 
              System.out.println("显示浅绿色按钮。");
         }
    }
    //Summer按钮类:具体产品
    class SummerButton implements Button {
         public void display() { 
              System.out.println("显示浅蓝色按钮。");
         }
    }    

    文本框:

    //文本框接口:抽象产品
    interface TextField {
        public void display();
    }
    //Spring文本框类:具体产品
    class SpringTextField implements TextField {
        public void display() { 
            System.out.println("显示绿色边框文本框。");
        }
    }
    //Summer文本框类:具体产品
    class SummerTextField implements TextField {
        public void display() { 
              System.out.println("显示蓝色边框文本框。");
         }
    }

    组合框:

    //组合框接口:抽象产品
    interface ComboBox {
        public void display();
    }
    //Spring组合框类:具体产品
    class SpringComboBox implements ComboBox {
        public void display() { 
             System.out.println("显示绿色边框组合框。");
        }
    }
    //Summer组合框类:具体产品
    class SummerComboBox implements ComboBox {
        public void display() { 
             System.out.println("显示蓝色边框组合框。");
        }
    }

    开始创建界面皮肤工厂:

    //界面皮肤工厂接口:抽象工厂
    interface SkinFactory {
        public Button createButton();
        public TextField createTextField();
        public ComboBox createComboBox();
    }
    //Spring皮肤工厂:具体工厂
    class SpringSkinFactory implements SkinFactory { 
         public Button createButton() {
             return new SpringButton();
         }
    
         public TextField createTextField() { 
             return new SpringTextField();
         }
    
         public ComboBox createComboBox() { 
             return new SpringComboBox();
         }
    }
    //Summer皮肤工厂:具体工厂
    class SummerSkinFactory implements SkinFactory {
         public Button createButton() { 
             return new SummerButton();
         }
    
         public TextField createTextField() { 
             return new SummerTextField();
         }
    
         public ComboBox createComboBox() { 
             return new SummerComboBox();
         }
    }

    为了让系统具备良好的灵活性和可扩展性,我们引入了工具类XMLUtil和配置文件,

    XMLUtil类的代码如下所示:

    import javax.xml.parsers.*; 
    import org.w3c.dom.*;
    import org.xml.sax.SAXException; 
    import java.io.*;
    
    public class XMLUtil {
            //该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
            public static Object getBean() {
                try {
                    //创建文档对象
                    DocumentBuilderFactory dFactory = DocumentBuilderFactory
                    DocumentBuilder builder = dFactory.newDocumentBuilder();
                    Document doc;
                    doc = builder.parse(new File("config.xml"));
                    //获取包含类名的文本节点
                    NodeList nl = doc.getElementsByTagName("className");
                    Node classNode = nl.item(0).getFirstChild();
                    String cName = classNode.getNodeValue();
                    //通过类名生成实例对象并将其返回
                    Class c = Class.forName(cName);
                    Object obj = c.newInstance();
                    return obj;
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
          }
    }

    配置文件config.xml中存储了具体工厂类的类名,代码如下所示:

    <?xml version="1.0"?>
    <config>
        <className>SpringSkinFactory</className>
    </config>

    编写如下客户端测试代码:

    class Client {
         public static void main(String args[]) {
               //使用抽象层定义SkinFactory factory;
               Button bt; TextField tf; ComboBox cb;
               factory = (SkinFactory)XMLUtil.getBean(); 
               bt = factory.createButton();
               tf = factory.createTextField(); 
               cb = factory.createComboBox(); 
           bt.display(); tf.display(); cb.display(); } }

    编译并运行程序,输出结果如下:

    显示浅绿色按钮。
    显示绿色边框文本框。
    显示绿色边框组合框。

    如果需要更换皮肤,只需修改配置文件即可,在实际环境中,我们可以提供可视化界面,例如菜单或者窗口来修改配置文件,用户无须直接修改配置文件。如果需要增加新的皮肤,只需增加一族新的具体组件并对应提供一个新的具体工厂,修改配置文件即可使用新的皮肤, 原有代码无须修改,符合“开闭原则”。

  • 相关阅读:
    低级格式化
    winhex恢复误GHOST系统造成的数据丢失
    共享进程空间内容(修的进程空间代码/HOOK)
    WinDbg 入门教程
    遍历删除当前目录下所有文件
    VC/MFC非模态对话框实例
    经典SQL语句
    C++实现系统服务暂停、停止、启动
    汇编中的管道操作方法
    Dll2lib探究
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13801579.html
Copyright © 2011-2022 走看看