码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式三:抽象工厂模式

时间:2015-05-12 17:22:24      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:设计模式

抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品。

抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。

在抽象工厂模式结构图中包含如下几个角色:

       AbstractFactory(抽象工厂):它声明了一组用于创建一族产品的方法,每一个方法对应一种产品。

       ● ConcreteFactory(具体工厂):它实现了在抽象工厂中声明的创建产品的方法,生成一组具体产品,这些产品构成了一个产品族,每一个产品都位于某个产品等级结构中。

       AbstractProduct(抽象产品):它为每种产品声明接口,在抽象产品中声明了产品所具有的业务方法。

       ConcreteProduct(具体产品):它定义具体工厂生产的具体产品对象,实现抽象产品接口中声明的业务方法。

  在抽象工厂中声明了多个工厂方法,用于创建不同类型的产品,抽象工厂可以是接口,也可以是抽象类或者具体类,其典型代码如下所示:


abstract class AbstractFactory {  
public abstract AbstractProductA createProductA(); //工厂方法一  
public abstract AbstractProductB createProductB(); //工厂方法二  
……  
} 

具体工厂实现了抽象工厂,每一个具体的工厂方法可以返回一个特定的产品对象,而同一个具体工厂所创建的产品对象构成了一个产品族。对于每一个具体工厂类,其典型代码如下所示:
    class ConcreteFactory1 extends AbstractFactory {  
        //工厂方法一  
    public AbstractProductA createProductA() {  
        return new ConcreteProductA1();  
    }  
      
    //工厂方法二  
    public AbstractProductB createProductB() {  
        return new ConcreteProductB1();  
    }  
      
    ……  
    }  

    //在本实例中我们对代码进行了大量简化,实际使用时,界面组件的初始化代码较为复杂,还需要使用JDK中一些已有类,为了突出核心代码,在此只提供框架代码和演示输出。  
    //按钮接口:抽象产品  
    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();  
        }  
    }  

    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.newInstance();  
                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;  
            }  
        }  
    }  

    <?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();  
        }  
    }  

显示浅绿色按钮。

显示绿色边框文本框。

显示绿色边框组合框。

在抽象工厂模式中,增加新的产品族很方便,但是增加新的产品等级结构很麻烦,抽象工厂模式的这种性质称为“开闭原则”的倾斜性。“开闭原则”要求系统对扩展开放,对修改封闭,通过扩展达到增强其功能的目的,对于涉及到多个产品族与多个产品等级结构的系统,其功能增强包括两方面:

  (1) 增加产品族:对于增加新的产品族,抽象工厂模式很好地支持了“开闭原则”,只需要增加具体产品并对应增加一个新的具体工厂,对已有代码无须做任何修改。

       (2) 增加新的产品等级结构:对于增加新的产品等级结构,需要修改所有的工厂角色,包括抽象工厂类,在所有的工厂类中都需要增加生产新产品的方法,违背了“开闭原则”。

       正因为抽象工厂模式存在“开闭原则”的倾斜性,它以一种倾斜的方式来满足“开闭原则”,为增加新产品族提供方便,但不能为增加新产品结构提供这样的方便,因此要求设计人员在设计之初就能够全面考虑,不会在设计完成之后向系统中增加新的产品等级结构,也不会删除已有的产品等级结构,否则将会导致系统出现较大的修改,为后续维护工作带来诸多麻烦。

抽象工厂模式总结

1. 主要优点

       抽象工厂模式的主要优点如下:

       (1) 抽象工厂模式隔离了具体类的生成,使得客户并不需要知道什么被创建。由于这种隔离,更换一个具体工厂就变得相对容易,所有的具体工厂都实现了抽象工厂中定义的那些公共接口,因此只需改变具体工厂的实例,就可以在某种程度上改变整个软件系统的行为。

       (2) 当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。

       (3) 增加新的产品族很方便,无须修改已有系统,符合“开闭原则”。

 

       2. 主要缺点

       抽象工厂模式的主要缺点如下:

       增加新的产品等级结构麻烦,需要对原有系统进行较大的修改,甚至需要修改抽象层代码,这显然会带来较大的不便,违背了“开闭原则”。

 

       3. 适用场景

       在以下情况下可以考虑使用抽象工厂模式:

       (1) 一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有类型的工厂模式都是很重要的,用户无须关心对象的创建过程,将对象的创建和使用解耦。

       (2) 系统中有多于一个的产品族,而每次只使用其中某一产品族。可以通过配置文件等方式来使得用户可以动态改变产品族,也可以很方便地增加新的产品族。

       (3) 属于同一个产品族的产品将在一起使用,这一约束必须在系统的设计中体现出来。同一个产品族中的产品可以是没有任何关系的对象,但是它们都具有一些共同的约束,如同一操作系统下的按钮和文本框,按钮与文本框之间没有直接关系,但它们都是属于某一操作系统的,此时具有一个共同的约束条件:操作系统的类型。

       (4) 产品等级结构稳定,设计完成之后,不会向系统中增加新的产品等级结构或者删除已有的产品等级结构。


设计模式三:抽象工厂模式

标签:设计模式

原文地址:http://blog.csdn.net/caowei0403/article/details/45669773

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!