zoukankan      html  css  js  c++  java
  • 抽象工厂

    一,概念

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

     

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

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

    二,代码

    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
    }

     

     

  • 相关阅读:
    Linux常用命令(文件常用命令)
    Spring中的核心思想
    AOP中重要概念
    Spring框架中2种生成代理对象的方法
    python模块详解 | psutil
    Linux学习笔记 | 常见错误之无法获得锁
    python学习笔记 | 列表去重
    CentOS | python3.7安装指南
    selenium爬虫 | 爬取疫情实时动态(二)
    selenium爬虫 | 爬取疫情实时动态
  • 原文地址:https://www.cnblogs.com/xiashengwang/p/2578794.html
Copyright © 2011-2022 走看看