zoukankan      html  css  js  c++  java
  • 抽象工厂模式(Abstract Factory)

    1.参考文献

    参考文献1:http://blog.csdn.net/ipqxiang/archive/2007/12/20/1955677.aspx

    参考文献2:http://baike.baidu.com/view/1580269.htm#sub1580269

    参考3:http://en.wikipedia.org/wiki/Abstract_factory_pattern#Java

    参考文献4:反射在工厂模式上的应用

    2.概念描述:

          抽象工厂模式是所有形态的工厂模式中最为抽象和最具一般性的一种形态。抽象工厂模式是指当有多个抽象角色时,使用的一种工厂模式。抽象工厂模式可以向客户端(Client)提供一个接口,使客户端在不必指定产品的具体的情况下,创建多个产品族中的产品对象(只需要提供抽象工程实例)。

      根据LSP原则,任何接受父类型的地方,都应当能够接受子类型(比如ConcreteFactory1ConcreteFactory2都是AbstractFactory的子类型,因此父类型AbstractFactory的对象能够使用子类型进行实例化)。

          因此,实际上系统所需要的,仅仅是类型与这些抽象产品角色相同的一些实例(要的是ProductA1ProductA2),而不是这些抽象产品的实例(abstractFactoryAabstractFactoryB)。换言之,也就是这些抽象产品的具体子类的实例。工厂类负责创建抽象产品的具体子类的实例。

    3.实例1:

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace AbstractFactory
    {
        //抽象工厂类
        abstract class AbstractFactory
        {
            //包含创建产品的两个抽象方法
            abstract public AbstractProductA CreateProductA();
            abstract public AbstractProductB CreateProductB();
        }
        //创建产品的具体对象,继承自抽象工厂,并重写方法。
        class ConcreteFactory1 : AbstractFactory
        {
            public override  AbstractProductA CreateProductA()
            {
                return new ProductA1();
            }
            public override AbstractProductB CreateProductB()
            {
                return new ProductB1();
            }
        }
        class ConcreteFactory2 : AbstractFactory
        {
            public override AbstractProductA CreateProductA()
            {
                return new ProductA2();
            }
            public override AbstractProductB CreateProductB()
            {
                return new ProductB2();
            }
        }
        abstract class AbstractProductA
        {
        }
        class ProductA1 : AbstractProductA
        {
        }
        class ProductA2 : AbstractProductA
        {
        }
        abstract class AbstractProductB
        {
            abstract public void Interact(AbstractProductA a);
        }
        class ProductB1 : AbstractProductB
        {
            public override void Interact(AbstractProductA a)
            {
                Console.WriteLine(this.GetType().Name+" Interact With "+a.GetType().Name);
            }
        }
        class ProductB2 : AbstractProductB
        {
            public override void Interact(AbstractProductA a)
            {
                Console.WriteLine(this.GetType().Name + " Interact With " + a.GetType().Name);
            }
        }
        class Client
        {
            //成员变量
            private AbstractProductA abstractProductA;
            private AbstractProductB abstractProductB;
            //构造函数
            public Client(AbstractFactory abstractFactory)
            {
                //抽象工厂创建抽象产品
                abstractProductA = abstractFactory.CreateProductA();
                abstractProductB = abstractFactory.CreateProductB();
            }
            public void run()
            {
                abstractProductB.Interact(abstractProductA);
            }
        }
        class MainApp
        {
            public static void Main()
            {
                AbstractFactory factory1 = new ConcreteFactory1();
                Client c1 = new Client(factory1);
                c1.run();
                AbstractFactory factory2 = new ConcreteFactory2();
                Client c2 = new Client(factory2);
                c2.run();
            }
        }
    }

    运行结果:

    4.实例1:java版本

    View Code
    //抽象工厂类,里面定义了创建AbstractProductA和AbstractProductB的方法
    public interface AbstractFactory {
        public AbstractProductA createProductA();
        public AbstractProductB createProductB();
    }
    
    //抽象产品类,里面定义了这一类产品的一个方法paintA()
    public interface AbstractProductA {
        public void paintA();
    }
    
    //抽象产品类,里面定义了这一类产品的一个方法paintB()
    public interface AbstractProductB {
        public void paintB();
    }
    
    //用于创建产品A和B的具体工厂类,这个类实现了抽象工厂类
    public class ConcreateFactoryA1B1 implements AbstractFactory {
    
        /**
         * 返回具体产品ProductA1
         */
        @Override
        public AbstractProductA createProductA() {
            // TODO Auto-generated method stub
            return new ProductA1();
        }
    
        /**
         * 返回具体产品ProductB1
         */
        @Override
        public AbstractProductB createProductB() {
            // TODO Auto-generated method stub
            return new ProductB1();
        }
    }
    
    public class ConcreateFactoryA1B2 implements AbstractFactory {
    
        @Override
        public AbstractProductA createProductA() {
            // TODO Auto-generated method stub
            return new ProductA1();
        }
    
        @Override
        public AbstractProductB createProductB() {
            // TODO Auto-generated method stub
            return new ProductB2();
        }
    }
    
    public class ConcreateFactoryA2B1 implements AbstractFactory {
    
        @Override
        public AbstractProductA createProductA() {
            // TODO Auto-generated method stub
            return new ProductA2();
        }
    
        @Override
        public AbstractProductB createProductB() {
            // TODO Auto-generated method stub
            return new ProductB1();
        }
    }
    
    public class ConcreateFactoryA2B2 implements AbstractFactory {
    
        @Override
        public AbstractProductA createProductA() {
            // TODO Auto-generated method stub
            return new ProductA2();
        } 
    
        @Override
        public AbstractProductB createProductB() {
            // TODO Auto-generated method stub
            return new ProductB2();
        }
    }
    
    /**
     * 具体产品类,实现抽象产品类
     */
    public class ProductA1 implements AbstractProductA {
    
        //具体产品类重写了抽象产品类的paintA()方法
        @Override
        public void paintA() {
            // TODO Auto-generated method stub
            System.out.println("this is ProductA1");    
        }
    }
    
    public class ProductA2 implements AbstractProductA {
    
        @Override
        public void paintA() {
            // TODO Auto-generated method stub
            System.out.println("this is ProductA2");
        }
    }
    
    public class ProductB1 implements AbstractProductB {
    
        @Override
        public void paintB() {
            // TODO Auto-generated method stub
            System.out.println("this is ProductB1");
        }
    }
    
    public class ProductB2 implements AbstractProductB {
    
        @Override
        public void paintB() {
            // TODO Auto-generated method stub
            System.out.println("this is ProductB2");
        }
    }
    
    /**
     * 客户端类
     * 使用抽象工厂创建抽象产品,具体创建哪一类产品在运行时定义
     */
    public class Application {
        public Application(AbstractFactory factory)
        {
            AbstractProductA productA=factory.createProductA();
            productA.paintA();
            AbstractProductB productB=factory.createProductB();
            productB.paintB();
        }
    }
    
    public class ApplicationRunner {
        private static int FACTORY_TYPE=11;
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            AbstractFactory factory = null;
            //在这个判断中定义需要使用哪一个具体工厂类来生产产品
            switch (FACTORY_TYPE) {
            case 11:
                factory = new ConcreateFactoryA1B1();
                break;
            case 12:
                factory = new ConcreateFactoryA1B2();
                break;
            case 21:
                factory = new ConcreateFactoryA2B1();
                break;
            case 22:
                factory = new ConcreateFactoryA2B2();
                break;
            }
            new Application(factory);
        }
    }

    运行结果:

    this is ProductA1
    this is ProductB1

    5.实例2:

    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    //Herbivore:草食动物
    //Carnivore:食肉动物
    namespace AbstractFactory
    {
        //大陆抽象类
        abstract class ContinentFactory
        {
            //不论什么大陆都有草食动物和肉食动物
            public abstract Herbivore CreateHerbivore();
            public abstract Carnivore CreateCarnivore();
        }
        //非洲类
        class AfricaFactory : ContinentFactory
        {
            //返回一个具体的非洲大陆上的草食动物Wildebeest
            public override Herbivore CreateHerbivore()
            {
                return new Wildebeest();
            }
            //重写肉食动物方法,返回一个具体的非洲大陆上的动物Lion
            public override Carnivore CreateCarnivore()
            {
                return new Lion();
            }
        }
    
        //美洲类
        class AmericaFactory : ContinentFactory
        {
            //返回具体实例,美洲大陆上的草食动物Bison
            public override Herbivore CreateHerbivore()
            {
                return new Bison();
            }
            //返回具体实例,美洲大陆上的肉食动物Wolf
            public override Carnivore CreateCarnivore()
            {
                return new Wolf();
            }
        }
    
        //草食动物抽象类
        abstract class Herbivore
        {
        }
        //肉食动物抽象类,包含抽象方法eat
        abstract class Carnivore
        {
            abstract public void Eat(Herbivore h);//食物链中肉食动物吃草食动物
        }
        //非洲动物:Wildebeest和 Lion
        class Wildebeest : Herbivore
        {
        }
        //抽象方法必须override
        class Lion : Carnivore
        {
            public override void Eat(Herbivore h)
            {
                Console.WriteLine(this+" eat "+h);
            }
        }
        //美洲动物: Bison和Wolf
        class Bison : Herbivore
        {
        }
        //抽象方法必须override
        class Wolf : Carnivore
        {
            public override void Eat(Herbivore h)
            {
                Console.WriteLine(this+" eat "+h);
            }
        }
        class AnimalWorld
        {
            //成员变量,抽象实体herbivore和carnivore
            private Herbivore herbivore;
            private Carnivore carnivore;
            //构造函数
            public AnimalWorld(ContinentFactory continent)
            {
                herbivore = continent.CreateHerbivore();//实例化
                carnivore = continent.CreateCarnivore();
            }
            public void RunFoodChain()
            {
                carnivore.Eat(herbivore);
            }
        }
        class GameApp
        {
            public static void Main()
            {
                ContinentFactory africa = new AfricaFactory();
                AnimalWorld a1 = new AnimalWorld(africa);
                a1.RunFoodChain();
                ContinentFactory america = new AmericaFactory();
                AnimalWorld a2 = new AnimalWorld(america);
                a2.RunFoodChain();
            }
        }
    }

    运行结果:

    6.抽象工厂的起源(PS:2011-11-2)

    据说最早的应用是用来创建在不同操作系统的视窗环境下都能够运行的系统。比如在Windows与Unix系统下都有视窗环境的构件(如WinButton和LinuxButton),在每一个操作系统中,都有一个视窗构件组成的构件家族。我们可以通过一个抽象角色给出功能描述,而由具体子类给出不同操作系统下的具体实现,如图:

    此模式为一个产品家族提供了统一的创建接口。当需要这个产品家族的某一系列的时候,可以从抽象工厂中选出相对系的系列来创建一个具体的工厂类别。

    假设我们有一种产品接口 Button ,这种产品都支持多种系列,比如 Linux 系列和 Windows 系列。这样每个系列的产品分别是 LinuxButton, WinButton。为了可以在运行时刻创建一个系列的产品族,我们可以为每个系列的产品族建立一个工厂LinuxFactory 和 WinFactory 。每个工厂都有一个方法 CreateButton  并返回对应的产品,可以将这个方法抽象成一个接口 AbstractFactory 。这样在运行时刻我们可以选择创建需要的产品系列。

    7.代码实例

    7.1接口Button

    View Code
    public interface Button {
        public void paint();
    }

    7.2Linux系统下的Button:LinuxButton

    View Code
    public class LinuxButton implements Button {
    
        @Override
        public void paint() {
            // TODO Auto-generated method stub
            System.out.println("I'm a LinuxButton!");
        }
    }

    7.3Windows系统下的Button:WinButton

    View Code
    public class WinButton implements Button {
    
        @Override
        public void paint() {
            // TODO Auto-generated method stub
            System.out.println("I'm a WinButton!");
        }
    }

    7.4视窗的抽象工厂类GUIFactory

    View Code
    public interface GUIFactory {
        public Button createButton();
    }

    7.5创建WinButton的工厂类:WinFactory

    View Code
    public class WinFactory implements GUIFactory {
    
        @Override
        public Button createButton() {
            // TODO Auto-generated method stub
            return new WinButton();//返回WinButton对象
        }
    }

    7.6创建LinuxButton的工厂类:LinuxFactory

    View Code
    public class LinuxFactory implements GUIFactory {
    
        @Override
        public Button createButton() {
            // TODO Auto-generated method stub
            return new LinuxButton();//返回LinuxButton对象
        }
    }

    7.7创建Button的应用程序:Application

    View Code
    public class Application {
        public Application(GUIFactory factory)
        {
            Button button=factory.createButton();//使用工程类来创建对象
            button.paint();
        }    
    }

    7.8主函数类:ApplicationRunner

    View Code
    public class ApplicationRunner {
        private static int OS_TYPE=0;
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            new Application(createSpecOSFactory());
        }
        
        /**
         * @param OS_TYPE
         * 传入参数表示操作系统类型
         * return 对应操作系统的工厂类
         */
        public static GUIFactory createSpecOSFactory()
        {
            if(OS_TYPE==0)
                return new WinFactory();
            else
                return new LinuxFactory();
        }
    }

     8.实现可配置的抽象工厂模式(ps:2012-5-30)

      参考前面写过的一片文章:反射在工厂模式上的应用。在这片文章中,就实现了可配置化。在原先的主函数类:ApplicationRunner中,我们需要定义一个OS_TYPE变量,然后根据OS_TYPE变量的数值来判断到底是Linux系统还是Windows系统,如果操作系统的种类很多,并且添加了操作系统的种类,那么就必须修改系统代码来应对操作系统种类的增加。这样不易维护,我们可以通过配置文件来修改原来的代码,使得系统更加灵活。

      首先,我们在项目包目录下添加配置文件OS.properties,文件内容如下:

    Linux=edu.sjtu.erplab.designpattern.abstractfactory3.LinuxFactory
    Windows=edu.sjtu.erplab.designpattern.abstractfactory3.WinFactory

      然后,在这里我们引用博客:反射在工厂模式上的应用中所用到的配置文件操作类Init,代码如下:

    Init.java

    View Code
    package edu.sjtu.erplab.designpattern.abstractfactory3;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.Properties;
    
    public class Init {
        
        public static Properties getPro()
        {
            Properties pro=new Properties();
            InputStream in=null;
            try {
                in=Init.class.getResourceAsStream("OS.properties");//从此类所在的包下取资源
                pro.load(in);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            finally{
                try{
                    in.close();
                }catch(IOException e){
                    e.printStackTrace();
                }
            }
            
            return pro;
        }
    }

      最后,我们对ApplicationRunner稍作修改,修改后的ApplicationRunner代码如下:

    ApplicationRunner.java

    View Code
    package edu.sjtu.erplab.designpattern.abstractfactory3;
    
    import java.util.Properties;
    
    public class ApplicationRunner {
        public static void main(String[] args) {
            new Application(getSpecOSFactory("Windows"));
            //new Application(getSpecOSFactory("Linux"));
        }
    
        static GUIFactory getSpecOSFactory(String osType) {
            Properties pro = Init.getPro();
            GUIFactory factory = null;
    
            try {
                factory = (GUIFactory) Class.forName(pro.getProperty(osType))
                        .newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return factory;
        }
    
    }

    可以发现,用户不需要知道Windows和Linux类型的窗口的具体实现,只需要在客户端中传入Windows或者Linux这样的参数,就可以动态创建具体的产品。

    作者:xwdreamer
    欢迎任何形式的转载,但请务必注明出处。
    分享到:
  • 相关阅读:
    gw经销商上传部分代码
    lib
    【转】sql server的随机函数newID()和RAND()
    【源码】仿qq记住登录信息
    关于ConfigurationManager类
    oracle 10 协议适配器错误解决办法
    配置对象数据源时,无法找到业务对象的解决办法
    private的由来,让能你很容易地区分private与protected的用法!
    大树扎根不稳,缘何不倒?
    Html服务器控件常用属性InnerHtml属性及InnerText属性的区别
  • 原文地址:https://www.cnblogs.com/xwdreamer/p/2297026.html
Copyright © 2011-2022 走看看