抽象工厂
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
}