雁过请留痕...
代码改变世界

抽象工厂

2011-09-20 17:58  xiashengwang  阅读(272)  评论(0编辑  收藏  举报

一,概念

提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类

 

个人理解:抽象工厂是一种更高层次的多态应用。理解透抽象工厂,能更好的理解接口,抽象类在多态方面的特性,以及面向对象的思想在解决复杂问题时强大作用。当然,这本来就是模式要解决的问题。

这个代码有点多,从例子的一步一步改进中,可以看出抽象工厂的由来。

二,代码

using System;
using System.Collections.Generic;
using System.Text;

namespace CsharpBase.DesignPattern.AbstrctFactory
{
    /// <summary>
    /// 名称:抽象工厂
    /// 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类
    /// </summary>
    class AbstractFactoryDemo
    {
        public static void Run()
        {
            //Client.Test();
            //ClientOne.Run();
            //ChinaSalary.Calculator.Run();
            //AmerianSalary.Calculator.Run();
            //CombineSalary.Calculator.Run();
            //InterfaceSalary.Calculator.Run();
            //factorySalary.Calculator.Run();
            AbstractFactorySalary.Calculator.Run();
            
        }
    }

    #region original description
    /// <summary>
    /// client-->abstractFactory-->productA,productB
    /// abstract factory
    /// </summary>
    public abstract class AbstractFactory
    {
        public abstract AbstractProductA GetProductA();
        public abstract AbstractProductB GetProductB();
    }
    /// <summary>
    /// abstract ProductA
    /// </summary>
    public abstract class AbstractProductA
    {
    }
    /// <summary>
    /// abstract ProductB
    /// </summary>
    public abstract class AbstractProductB
    {
        public abstract void Interact(AbstractProductA productA);
    }
    public class ProductA1 : AbstractProductA
    {
    }
    public class ProductB1 : AbstractProductB
    {
        public override void Interact(AbstractProductA productA)
        {
            Console.WriteLine(this.GetType().Name + " interact " + productA.GetType().Name);
        }
    }
    public class ProductA2 : AbstractProductA
    {
    }
    public class ProductB2 : AbstractProductB
    {
        public override void Interact(AbstractProductA productA)
        {
            Console.WriteLine(this.GetType().Name + " interact " + productA.GetType().Name);
        }
    }

    public class ConcreteFactory1 : AbstractFactory
    {
        public override AbstractProductA GetProductA()
        {
            return new ProductA1();
        }
        public override AbstractProductB GetProductB()
        {
            return new ProductB1();
        }
    }

    public class ConcreteFactory2 : AbstractFactory
    {
        public override AbstractProductA GetProductA()
        {
            return new ProductA2();
        }
        public override AbstractProductB GetProductB()
        {
            return new ProductB2();
        }
    }

    public class Client
    {
        public static void Test()
        {
            AbstractProductA a;
            AbstractProductB b;
            AbstractFactory factory;
            string menuItem = "";
            menuItem = Console.ReadLine();
            if (menuItem == "Skin1")
            {
                factory = new ConcreteFactory1();
            }
            else if (menuItem == "Skin2")
            {
                factory = new ConcreteFactory2();
            }
            else
            {
                factory = null;
            }

            a = factory.GetProductA();
            b = factory.GetProductB();
            b.Interact(a);
        }
    }

    #endregion

    #region Sample one
    /// <summary>
    /// 每个大陆都有草食动物和肉食动物,针对不同的大陆,可以自由配置
    /// </summary>
    public abstract class ContinentFactory
    {
        public abstract Herbivore GetHerbivore();
        public abstract Carnivore GetCarnivore();
    }

    public abstract class Herbivore
    {
    }

    public abstract class Carnivore
    {
        public abstract void Eat(Herbivore h);
    }

    public class Wildebeest : Herbivore
    {
    }

    public class Lion : Carnivore
    {
        public override void Eat(Herbivore h)
        {
            Console.WriteLine(this.GetType().Name + " eat " + h.GetType().Name);
        }
    }

    public class Bison : Herbivore
    {
    }

    public class Wolf : Carnivore
    {
        public override void Eat(Herbivore h)
        {
            Console.WriteLine(this.GetType().Name + " eat " + h.GetType().Name);
        }
    }

    public class AfricaFactory : ContinentFactory
    {
        public override Herbivore GetHerbivore()
        {
            return new Wildebeest();
        }
        public override Carnivore GetCarnivore()
        {
            return new Lion();
        }
    }

    public class AmericalFactory : ContinentFactory
    {
        public override Herbivore GetHerbivore()
        {
            return new Bison();
        }
        public override Carnivore GetCarnivore()
        {
            return new Wolf();
        }
    }
    public class AnimalWorld
    {
        private Herbivore herbivore;
        private Carnivore carnivore;
        public AnimalWorld(ContinentFactory factory)
        {
            herbivore = factory.GetHerbivore();
            carnivore = factory.GetCarnivore();
        }
        public void RunFoodChain()
        {
            carnivore.Eat(herbivore);
        }
    }
    public class ClientOne
    {
        public static void Run()
        {
            ContinentFactory factory;
            AnimalWorld animalWorld;

            factory = new AfricaFactory();
            animalWorld = new AnimalWorld(factory);
            animalWorld.RunFoodChain();

            factory = new AmericalFactory();
            animalWorld = new AnimalWorld(factory);
            animalWorld.RunFoodChain();
        }
    }

    #endregion

    #region Sample two
    namespace ChinaSalary
    {
        //    中国企业需要一项简单的财务计算:每月月底,财务人员要计算员工的工资。

        //员工的工资 = (基本工资 + 奖金 - 个人所得税)。这是一个放之四海皆准的运算法则。

        //为了简化系统,我们假设员工基本工资总是4000美金。

        //中国企业奖金和个人所得税的计算规则是:

        //         奖金 = 基本工资(4000) * 10%

        //         个人所得税 = (基本工资 + 奖金) * 40%

        //我们现在要为此构建一个软件系统(代号叫Softo),满足中国企业的需求。

        /// <summary>
        /// 共用的常量
        /// </summary>
        public class Const
        {
            public static readonly double BASE_SALARY = 4000;
        }

        /// <summary>
        /// 中国个人奖金
        /// </summary>
        public class ChinaBonus
        {
            public double Calculate()
            {
                return Const.BASE_SALARY * 0.1;
            }
        }

        /// <summary>
        /// 个人所得税
        /// </summary>
        public class ChinaTax
        {
            public double Calculate()
            {
                return (Const.BASE_SALARY * 0.1 + Const.BASE_SALARY) * 0.4;
            }
        }

        public class Calculator
        {
            public static void Run()
            {
                ChinaBonus bonus = new ChinaBonus();
                double bonusValue = bonus.Calculate();

                ChinaTax tax = new ChinaTax();
                double taxValue = tax.Calculate();

                double salary = Const.BASE_SALARY + bonusValue - taxValue;

                Console.WriteLine("Chian salary is:" + salary);
            }
        }

    }

    namespace AmerianSalary
    {
        //    为了拓展国际市场,我们要把该系统移植给美国公司使用。

        //美国企业的工资计算同样是: 员工的工资 = 基本工资 + 奖金 - 个人所得税。

        //但是他们的奖金和个人所得税的计算规则不同于中国企业:

        //美国企业奖金和个人所得税的计算规则是:

        //        奖金 = 基本工资 * 15 %

        //        个人所得税 = (基本工资 * 5% + 奖金 * 25%)   

        /// <summary>
        /// 共用的常量
        /// </summary>
        public class Const
        {
            public static readonly double BASE_SALARY = 4000;
        }

        public class AmericanBonus
        {
            public double Calculate()
            {
                return Const.BASE_SALARY * 0.15;
            }
        }

        public class AmericanTax
        {
            public double Calculate()
            {
                return Const.BASE_SALARY * 0.05 + (Const.BASE_SALARY * 0.15) * 0.25;
            }
        }

        public class Calculator
        {
            public static void Run()
            {
                AmericanBonus bonus = new AmericanBonus();
                double bonusValue = bonus.Calculate();

                AmericanTax tax = new AmericanTax();
                double taxValue = tax.Calculate();

                double salary = Const.BASE_SALARY + bonusValue - taxValue;

                Console.WriteLine("American salary is:" + salary);
            }
        }
    }

    namespace CombineSalary
    {
        //    让我们回顾一下该系统的发展历程:

        //最初,我们只考虑将Softo系统运行于中国企业。但随着MaxDO公司业务向海外拓展, MaxDO需要将该系统移植给美国使用。

        //移植时,MaxDO不得不抛弃中国企业的业务规则类ChineseTax和ChineseBonus, 然后为美国企业新建两个业务规则类: AmericanTax,AmericanBonus。最后修改了业务规则调用Calculator类。

        //结果我们发现:每当Softo系统移植的时候,就抛弃原来的类。现在,如果中国联想集团要购买该系统,我们不得不再次抛弃AmericanTax,AmericanBonus,修改回原来的业务规则。

        //一个可以立即想到的做法就是在系统中保留所有业务规则模型,即保留中国和美国企业工资运算规则。
        /// <summary>
        /// 共用的常量
        /// </summary>
        public class Const
        {
            public static readonly double BASE_SALARY = 4000;
        }
        /// <summary>
        /// 中国个人奖金
        /// </summary>
        public class ChinaBonus
        {
            public double Calculate()
            {
                return Const.BASE_SALARY * 0.1;
            }
        }

        /// <summary>
        /// 个人所得税
        /// </summary>
        public class ChinaTax
        {
            public double Calculate()
            {
                return (Const.BASE_SALARY * 0.1 + Const.BASE_SALARY) * 0.4;
            }
        }
        public class AmericanBonus
        {
            public double Calculate()
            {
                return Const.BASE_SALARY * 0.15;
            }
        }

        public class AmericanTax
        {
            public double Calculate()
            {
                return Const.BASE_SALARY * 0.05 + (Const.BASE_SALARY * 0.15) * 0.25;
            }
        }

        public class Calculator
        {
            public static void Run()
            {
                string identity = "";
                identity = Console.ReadLine();

                if (identity == "C")
                {
                    ChinaBonus bonus = new ChinaBonus();
                    double bonusValue = bonus.Calculate();

                    ChinaTax tax = new ChinaTax();
                    double taxValue = tax.Calculate();

                    double salary = Const.BASE_SALARY + bonusValue - taxValue;

                    Console.WriteLine("Chian salary is:" + salary);
                }
                else if (identity == "A")
                {
                    AmericanBonus bonus = new AmericanBonus();
                    double bonusValue = bonus.Calculate();

                    AmericanTax tax = new AmericanTax();
                    double taxValue = tax.Calculate();

                    double salary = Const.BASE_SALARY + bonusValue - taxValue;

                    Console.WriteLine("American salary is:" + salary);
                }
                else
                {
                }
            }
        }
    }

    namespace InterfaceSalary
    {
        //        让移植工作更简单

        //前面系统的整合问题在于:当系统在客户在美国和中国企业间切换时仍然需要修改Caculator代码。

        //一个维护性良好的系统应该遵循“开闭原则”。即:封闭对原来代码的修改,开放对原来代码的扩展(如类的继承,接口的实现)

        //我们发现不论是中国企业还是美国企业,他们的业务运规则都采用同样的计算接口。 于是很自然地想到建立两个业务接口类Tax,Bonus,
        //然后让AmericanTax、AmericanBonus和ChineseTax、ChineseBonus分别实现这两个接口, 据此修正后的模型如下:

        public class Const
        {
            public static readonly double BASE_SALARY = 4000;
        }
        public interface IBonus
        {
            double Calculate();
        }
        public interface ITax
        {
            double Calculate();
        }
        /// <summary>
        /// 中国个人奖金
        /// </summary>
        public class ChinaBonus : IBonus
        {
            #region IBonus メンバ

            double IBonus.Calculate()
            {
                return Const.BASE_SALARY * 0.1;
            }

            #endregion
        }

        /// <summary>
        /// 个人所得税
        /// </summary>
        public class ChinaTax : ITax
        {
            #region ITax メンバ

            double ITax.Calculate()
            {
                return (Const.BASE_SALARY * 0.1 + Const.BASE_SALARY) * 0.4;
            }

            #endregion
        }
        public class AmericanBonus : IBonus
        {
            #region IBonus メンバ

            double IBonus.Calculate()
            {
                return Const.BASE_SALARY * 0.15;
            }

            #endregion
        }

        public class AmericanTax : ITax
        {
            #region ITax メンバ

            double ITax.Calculate()
            {
                return Const.BASE_SALARY * 0.05 + (Const.BASE_SALARY * 0.15) * 0.25;
            }

            #endregion
        }

        public class Calculator
        {
            public static void Run()
            {
                //接口没有解决问题,在客户端调用是,仍然需要切换代码。
                string identity = "";
                identity = Console.ReadLine();

                IBonus bonus = null;
                ITax tax = null;
                if (identity == "C")
                {
                    bonus = new ChinaBonus();
                    tax = new ChinaTax();
                }
                else if (identity == "A")
                {
                    bonus = new AmericanBonus();
                    tax = new AmericanTax();
                }
                else
                {
                }
                double bonusValue = bonus.Calculate();
                double taxValue = tax.Calculate();
                double salary = Const.BASE_SALARY + bonusValue - taxValue;
                Console.WriteLine(identity + ",China salary is:" + salary);
            }
        }
    }

    namespace factorySalary
    {
        public class Const
        {
            public static readonly double BASE_SALARY = 4000;
        }
        public interface IBonus
        {
            double Calculate();
        }
        public interface ITax
        {
            double Calculate();
        }
        /// <summary>
        /// 中国个人奖金
        /// </summary>
        public class ChinaBonus : IBonus
        {
            #region IBonus メンバ

            double IBonus.Calculate()
            {
                return Const.BASE_SALARY * 0.1;
            }

            #endregion
        }

        /// <summary>
        /// 个人所得税
        /// </summary>
        public class ChinaTax : ITax
        {
            #region ITax メンバ

            double ITax.Calculate()
            {
                return (Const.BASE_SALARY * 0.1 + Const.BASE_SALARY) * 0.4;
            }

            #endregion
        }
        public class AmericanBonus : IBonus
        {
            #region IBonus メンバ

            double IBonus.Calculate()
            {
                return Const.BASE_SALARY * 0.15;
            }

            #endregion
        }

        public class AmericanTax : ITax
        {
            #region ITax メンバ

            double ITax.Calculate()
            {
                return Const.BASE_SALARY * 0.05 + (Const.BASE_SALARY * 0.15) * 0.25;
            }

            #endregion
        }

        public class Factory
        {
            const string country = "American";
            public  ITax CreateTax()
            {
                if (country == "China")
                    return new ChinaTax();
                if (country == "American")
                     return new AmericanTax();
            }
            public IBonus CreateBouns()
            {
                if (country == "China")
                    return new ChinaBonus();
                if (country == "American")
                    return new AmericanBonus();
            }
        
        }

        public class Calculator
        {
            public static void Run()
            {
                //实际上工厂已经很好的完成了任务,但是注意到China,American是两个不同的组件,他们内部的方法
                //应该是不可分割的一个整体,应该统合到一起作为一个单独的factory,看抽象工厂
                Factory factory = new Factory();

                IBonus bonus = factory.CreateBouns();
                ITax tax = factory.CreateTax();

                double bonusValue = bonus.Calculate();
                double taxValue = tax.Calculate();
                double salary = Const.BASE_SALARY + bonusValue - taxValue;
                Console.WriteLine("salary is:" + salary);
            }
        }    
    }

    namespace AbstractFactorySalary
    {
        public class Const
        {
            public static double BASE_SALARY = 4000;
        }
        abstract class Tax
        {
            public abstract double Calculate();
        }
        abstract class Bonus
        {
            public abstract double Calculate();
        }
        class ChinaTax : Tax
        {
            public override double Calculate()
            {
                return (Const.BASE_SALARY * 0.1 + Const.BASE_SALARY) * 0.4;
            }
        }
        class ChinaBonus : Bonus
        {
            public override double Calculate()
            {
                return Const.BASE_SALARY * 0.1;
            }
        }
        class AmericanTax : Tax
        {
            public override double Calculate()
            {
                return Const.BASE_SALARY * 0.05 + (Const.BASE_SALARY * 0.15) * 0.25;
            }        
        }
        class AmericanBonus : Bonus
        {
            public override double Calculate()
            {
                return Const.BASE_SALARY * 0.15;
            }
        }
        abstract class CountryFactory
        {
            private static readonly string config_Mode = "China";//配置的值可以从config文件读取,至此所有的依赖就只和config文件相关。
            public abstract Tax GetTax();
            public abstract Bonus GetBonus();

            public static CountryFactory GetFactory()
            {
                if (config_Mode == "China")
                {
                    return new ChinaFactory();
                }
                else if (config_Mode == "American")
                {
                    return new AmericanFactory();
                }
                return null;
            }
        }

        class ChinaFactory : CountryFactory
        {
            public override Bonus GetBonus()
            {
                return new ChinaBonus();
            }
            public override Tax GetTax()
            {
                return new ChinaTax();
            }
        }
        class AmericanFactory : CountryFactory
        {
            public override Bonus GetBonus()
            {
                return new AmericanBonus();
            }
            public override Tax GetTax()
            {
                return new AmericanTax();
            }
        }

        class Calculator
        {
            public static void Run()
            { 
                CountryFactory factory = CountryFactory.GetFactory();
                Bonus bonus = factory.GetBonus();
                Tax tax = factory.GetTax();

                double bonusValue = bonus.Calculate();
                double taxValue = tax.Calculate();
                double salary = Const.BASE_SALARY + bonusValue - taxValue;

                Console.WriteLine("salary is:" + salary);            
            }
        }
    }

    #endregion
}