




已阅读5页,还剩89页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
设计模式,ABSTRACT FACTORY(抽象工厂),1. 意图提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。2. 别名K i t3. 动机考虑一个支持多种视感(look-and-feel)标准的用户界面工具包。,4. 适用性一个系统要独立于它的产品的创建、组合和表示时。一个系统要由多个产品系列中的一个来配置时。当你要强调一系列相关的产品对象的设计以便进行联合使用时。当你提供一个产品类库,而只想显示它们的接口而不是实现时。,5. 结构,6. 参与者AbstractFactory ( WidgetFactory ) 声明一个创建抽象产品对象的操作接口。ConcreteFactory ( MotifWidgetFactory,PMWidgetFactory ) 实现创建具体产品对象的操作。AbstractProduct ( Windows,ScrollBar) 为一类产品对象声明一个接口。ConcreteProduct ( MotifWindow,MotifScrollBar ) 定义一个将被相应的具体工厂创建的产品对象。 实现AbstractProduct接口。Client 仅使用由AbstractFactory和AbstractProduct类声明的接口。,7. 协作通常在运行时刻创建一个ConcreteFactroy类的实例。这一具体的工厂创建具有特定实现的产品对象。为创建不同的产品对象,客户应使用不同的具体工厂。 AbstractFactory将产品对象的创建延迟到它的ConcreteFactory子类。,8. 效果1) 它分离了具体的类:Abstract Factory模式帮助你控制一个应用创建的对象的类。因为一个工厂封装创建产品对象的责任和过程,它将客户与类的实现分离。客户通过它们的抽象接口操纵实例。产品的类名也在具体工厂的实现中被分离;它们不出现在客户代码中。2) 它使得易于交换产品系列:一个具体工厂类在一个应用中仅出现一次即在它初始化的时候。这使得改变一个应用的具体工厂变得很容易。它只需改变具体的工厂即可使用不同的产品配置,这是因为一个抽象工厂创建了一个完整的产品系列,所以整个产品系列会立刻改变。在我们的用户界面的例子中,我们仅需转换到相应的工厂对象并重新创建接口,就可实现从Motif窗口组件转换为Presentation Manager窗口组件。,3) 它有利于产品的一致性:当一个系列中的产品对象被设计成一起工作时,一个应用一次只能使用同一个系列中的对象,这一点很重要。而AbstractFactory很容易实现这一点。4) 难以支持新种类的产品:难以扩展抽象工厂以生产新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新种类的产品就需要扩展该工厂接口,这将涉及AbstractFactory类及其所有子类的改变。,抽象工厂举例,已经开发的项目使用sql server 2000数据库。但是在投入使用时,用户临时改变计划,使用免费的数据库 Access 2000.,不同之处:引用空间Sql server用:System.Data.SqlClientAccess用:System.Data.OleDbSql语句Sql Server用:Insert,GetDate,SubStringAccess用:Insert into,Now,Mid,class User private int _id; public int ID get return _id; set _id = value; private string _name; public string Name get return _name; set _name = value; ,class SqlserverUser public void Insert(User user) Console.WriteLine(在Sqlserver中给User表增加一条记录); public User GetUser(int id) Console.WriteLine(在Sqlserver中根据ID得到User表一条记录); return null; ,class Program static void Main(string args) User user = new User(); SqlserverUser su = new SqlserverUser(); su.Insert(user); su.GetUser(1); Console.Read(); ,用工厂方法实现,class User private int _id; public int ID get return _id; set _id = value; private string _name; public string Name get return _name; set _name = value; ,interface IUser void Insert(User user); User GetUser(int id); ,class SqlserverUser : IUser public void Insert(User user) Console.WriteLine(在Sqlserver中给User表增加一条记录); public User GetUser(int id) Console.WriteLine(在Sqlserver中根据ID得到User表一条记录); return null; ,class AccessUser : IUser public void Insert(User user) Console.WriteLine(在Access中给User表增加一条记录); public User GetUser(int id) Console.WriteLine(在Access中根据ID得到User表一条记录); return null; ,interface IFactory IUser CreateUser(); ,class SqlServerFactory : IFactory public IUser CreateUser() return new SqlserverUser(); class AccessFactory : IFactory public IUser CreateUser() return new AccessUser(); ,static void Main(string args) User user = new User(); IFactory factory = new AccessFactory(); IUser iu = factory.CreateUser(); iu.Insert(user); iu.GetUser(1); Console.Read(); ,用抽象工厂,class Department private int _id; public int ID get return _id; set _id = value; private string _deptName; public string DeptName get return _deptName; set _deptName = value; ,interface IDepartment void Insert(Department department); Department GetDepartment(int id); ,class SqlserverDepartment : IDepartment public void Insert(Department department) Console.WriteLine(在Sqlserver中给Department表增加一条记录); public Department GetDepartment(int id) Console.WriteLine(在Sqlserver中根据ID得到Department表一条记录); return null; ,class AccessDepartment : IDepartment public void Insert(Department department) Console.WriteLine(在Access中给Department表增加一条记录); public Department GetDepartment(int id) Console.WriteLine(在Access中根据ID得到Department表一条记录); return null; ,interface IFactory IUser CreateUser(); IDepartment CreateDepartment(); ,class SqlServerFactory : IFactory public IUser CreateUser() return new SqlserverUser(); public IDepartment CreateDepartment() return new SqlserverDepartment(); ,static void Main(string args) User user = new User(); Department dept = new Department(); IFactory factory = new AccessFactory(); IUser iu = factory.CreateUser(); iu.Insert(user); iu.GetUser(1); IDepartment id = factory.CreateDepartment(); id.Insert(dept); id.GetDepartment(1); Console.Read(); ,如果增加对新表的操作怎么办?如:增加一个Project表的操作修改工作:增加:IProject,SqlServerProject,AccessProject修改:IFactory,SqlserverFactory,AccessFactory,改进方法简单工厂来改进抽象工厂,class DataAccess private static readonly string db = Sqlserver; /private static readonly string db = Access; public static IUser CreateUser() IUser result = null; switch (db) case Sqlserver: result = new SqlserverUser(); break; case Access: result = new AccessUser(); break; return result; ,public static IDepartment CreateDepartment() IDepartment result = null; switch (db) case Sqlserver: result = new SqlserverDepartment(); break; case Access: result = new AccessDepartment(); break; return result; ,static void Main(string args) User user = new User(); Department dept = new Department(); IUser iu = DataAccess.CreateUser(); iu.Insert(user); iu.GetUser(1); IDepartment id = DataAccess.CreateDepartment(); id.Insert(dept); id.GetDepartment(1); Console.Read(); ,改进方法反射+抽象工厂,class DataAccess private static readonly string AssemblyName = 抽象工厂模式; private static readonly string db = Sqlserver; public static IUser CreateUser() string className = AssemblyName + . + db + User; return (IUser)Assembly.Load(AssemblyName).CreateInstance(className); public static IDepartment CreateDepartment() string className = AssemblyName + . + db + Department; return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className); ,改进方法反射+配置文件,class DataAccess private static readonly string AssemblyName = 抽象工厂模式; private static readonly string db = ConfigurationManager.AppSettingsDB; public static IUser CreateUser() string className = AssemblyName + . + db + User; return (IUser)Assembly.Load(AssemblyName).CreateInstance(className); public static IDepartment CreateDepartment() string className = AssemblyName + . + db + Department; return (IDepartment)Assembly.Load(AssemblyName).CreateInstance(className); ,三种工厂模式的比较,优点:工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅消费产品。简单工厂模式通过这种做法实现了对责任的分割。缺点:当产品有复杂的多层等级结构时,工厂类只有自己,以不变应万变,就是模式的缺点。因为工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。同时,系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,有可能造成工厂逻辑过于复杂。另外,简单工厂模式通常使用静态工厂方法,这使得无法由子类继承,造成工厂角色无法形成基于继承的等级结构。,简单工厂的特点,using System;public abstract class Lightpublic abstract void TurnOn();public abstract void TurnOff();,public class BulbLight : Lightpublic override void TurnOn()Console.WriteLine(Bulb Light is Turned on);public override void TurnOff()Console.WriteLine(Bulb Light is Turned off);public class TubeLight : Lightpublic override void TurnOn()Console.WriteLine(Tube Light is Turned on);public override void TurnOff()Console.WriteLine(Tube Light is Turned off);,public class LightSimpleFactorypublic Light Create(string LightType)if(LightType = Bulb)return new BulbLight();else if(LightType = Tube)return new TubeLight();elsereturn null;,public class Clientpublic static void Main()LightSimpleFactory lsf = new LightSimpleFactory();Light l = lsf.Create(Bulb);l.TurnOn();l.TurnOff();Console.WriteLine(-);l = lsf.Create(Tube);l.TurnOn();l.TurnOff();,工厂方法模式与简单工厂模式再结构上的不同不是很明显:工厂方法类的核心是一个抽象工厂类简单工厂模式把核心放在一个具体类上当系统扩展需要添加新的产品对象时,仅仅需要添加一个具体对象以及一个具体工厂对象,原有工厂对象不需要进行任何修改,也不需要修改客户端,很好的符合了“开放封闭”原则。而简单工厂模式在添加新产品对象后不得不修改工厂方法,扩展性不好。,工厂方法模式的特点,using System;public abstract class Light/抽象产品public abstract void TurnOn();public abstract void TurnOff();,public class BulbLight : Light/具体产品public override void TurnOn() Console.WriteLine(Bulb Light is Turned on); public override void TurnOff() Console.WriteLine(Bulb Light is Turned off); public class TubeLight : Light/具体产品public override void TurnOn() Console.WriteLine(Tube Light is Turned on); public override void TurnOff() Console.WriteLine(Tube Light is Turned off); ,public abstract class Creator/抽象工厂public abstract Light factory();public class BulbCreator : Creator/具体工厂public override Light factory() return new BulbLight(); public class TubeCreator : Creator/具体工厂public override Light factory() return new TubeLight(); ,public class Client/客户端public static void Main()Creator c1 = new BulbCreator();Creator c2 = new TubeCreator();Light l1 = c1.factory();Light l2 = c2.factory();l1.TurnOn();l1.TurnOff();Console.WriteLine(-);l2.TurnOn();l2.TurnOff();,抽象工厂模式,/ Abstract Factory pattern - Structural exampleusing System;/ AbstractFactoryabstract class AbstractFactory/ Methodsabstract public AbstractProductA CreateProductA();abstract public AbstractProductB CreateProductB();,/ ConcreteFactory1class ConcreteFactory1 : AbstractFactory/ Methodsoverride public AbstractProductA CreateProductA()return new ProductA1();override public AbstractProductB CreateProductB()return new ProductB1();,/ ConcreteFactory2class ConcreteFactory2 : AbstractFactory/ Methodsoverride public AbstractProductA CreateProductA()return new ProductA2();override public AbstractProductB CreateProductB()return new ProductB2();,/ AbstractProductAabstract class AbstractProductA/ AbstractProductBabstract class AbstractProductB/ Methodsabstract public void Interact( AbstractProductA a );,/ ProductA1class ProductA1 : AbstractProductA/ ProductB1class ProductB1 : AbstractProductB/ Methodsoverride public void Interact( AbstractProductA a )Console.WriteLine( this + interacts with + a );,/ ProductA2class ProductA2 : AbstractProductA/ ProductB2class ProductB2 : AbstractProductB/ Methodsoverride public void Interact( AbstractProductA a )Console.WriteLine( this + interacts with + a );,/ Client - the interaction environment of the productsclass Environment/ Fieldsprivate AbstractProductA AbstractProductA;private AbstractProductB AbstractProductB;/ Constructorspublic Environment( AbstractFactory factory )AbstractProductB = factory.CreateProductB();AbstractProductA = factory.CreateProductA();/ Methodspublic void Run()AbstractProductB.Interact( AbstractProduct A );,class ClientApppublic static void Main(string args)AbstractFactory factory1 = new ConcreteFactory1();Environment e1 = new Environment( factory1 );e1.Run();AbstractFactory factory2 = new ConcreteFactory2();Environment e2 = new Environment( factory2 );e2.Run();,虚拟案例,中国企业需要一项简单的财务计算:每月月底,财务人员要计算员工的工资。员工的工资 = (基本工资 + 奖金 - 个人所得税)。为了简化系统,假设员工基本工资总是4000美金。中国企业奖金和个人所得税的计算规则是:奖金 = 基本工资(4000) * 10%个人所得税 = (基本工资 + 奖金) * 40%构建一个软件系统(代号叫Softo),满足中国企业的需求。,案例分析,奖金(Bonus)、个人所得税(Tax)的计算是Softo系统的业务规则(Service)。工资的计算(Calculator)则调用业务规则(Service)来计算员工的实际工资。工资的计算作为业务规则的前端(或客户端Client)将提供给最终使用该系统的用户(财务人员)使用。,针对中国企业为系统建模,业务规则Service类的代码如下,using System;namespace ChineseSalary/ 公用的常量public class Constantpublic static double BASE_SALARY = 4000;,using System;namespace ChineseSalary/ 计算中国个人奖金public class ChineseBonus public double Calculate() return Constant.BASE_SALARY * 0.1;,using System;namespace ChineseSalary / 计算中国个人所得税public class ChineseTaxpublic double Calculate()return (Constant.BASE_SALARY + (Constant.BASE_SALARY * 0.1) * 0.4;,客户端代码,using System;namespace ChineseSalary / 客户端程式调用public class Calculator public static void Main(string args) ChineseBonus bonus = new ChineseBonus();double bonusValue = bonus.Calculate();ChineseTax tax = new ChineseTax();double taxValue = tax.Calculate();double salary = 4000 + bonusValue - taxValue; Console.WriteLine(“Chinese Salary is:” + salary);Console.ReadLine();,为了拓展国际市场,要把该系统移植给美国公司使用。 美国企业的工资计算同样是: 员工的工资 = 基本工资 + 奖金 - 个人所得税。奖金和个人所得税的计算规则不同于中国企业:奖金 = 基本工资 * 15 %个人所得税 = (基本工资 * 5% + 奖金 * 25%) 根据前面为中国企业建模经验,仅仅将ChineseTax、ChineseBonus修改为AmericanTax、AmericanBonus。,业务规则Service类的代码如下,using System;namespace AmericanSalary/ 公用的常量public class Constantpublic static double BASE_SALARY = 4000;,using System;namespace AmericanSalary/ 计算美国个人奖金public class AmericanBonuspublic double Calculate()return Constant.BASE_SALARY * 0.15;,using System;namespace AmericanSalary / 计算美国个人所得税public class AmericanTaxpublic double Calculate()return (Constant.BASE_SALARY*0.05 + (Constant.BASE_SALARY * 0.15*0.25) * 0.4;,客户端的调用代码,using System;namespace AmericanSalary/ 客户端程式调用public class Calculator public static void Main(string args) AmericanBonus bonus = new AmericanBonus();double bonusValue = bonus.Calculate();AmericanTax tax = new AmericanTax();double taxValue = tax.Calculate();double salary = 4000 + bonusValue - taxValue; Console.WriteLine(“American Salary is:” + salary);Console.ReadLine();,结果发现:每当Softo系统移植的时候,就抛弃原来的类。目前,如果中国联想集团要购买该系统,不得不再次抛弃AmericanTax,AmericanBonus,修改回原来的业务规则。一个能即时想到的做法就是在系统中保留所有业务规则模型,即保留中国和美国企业工资运算规则。,using System;namespace InterfaceSalary/ 客户端程式调用public class Calculator public static void Main(string args) Bonus bonus = new ChineseBonus();double bonusValue = bonus.Calculate();Tax tax = new ChineseTax();double taxValue = tax.Calculate();double salary = 4000 + bonusValue - taxValue; Console.WriteLine(“Chinaese Salary is:” + salary);Console.ReadLine();,只不过修改少了两处,不过仍然需要修改ChineseBonus,ChineseTax部分。致命的问题是:需要将这个移植工作转包给一个叫Hippo的软件公司。 由于版权问题,并未提供Softo系统的源码给Hippo公司,因此Hippo公司根本无法修改Calculator,导致实际上移植工作无法进行。,考虑增加一个工具类,using System;namespace FactorySalary/ Factory类public class Factorypublic Tax CreateTax()return new ChineseTax();public Bonus CreateBonus()return new ChineseBonus();,修改后的客户端代码,using System;namespace FactorySalary/ 客户端程式调用public class Calculator public static void Main(string args) Bonus bonus = new Factory().CreateBonus();double bonusValue = bonus.Calculate();Tax tax = new Factory().CreateTax();double taxValue = tax.Calculate();double salary = 4000 + bonusValue - taxValue; Console.WriteLine(“Chinaese Salary is:” + salary);Console.ReadLine();,设想一下:当该系统从中国企业移植到美国企业时,我们目前需要做什么?答案是: 对于Caculator类什么也不用做。需要做的是修改Factory类,using System;namespace FactorySalary/ Factory类public class Factorypublic Tax CreateTax()return new AmericanTax();public Bonus CreateBonus()return new AmericanBonus();,非常显然,前面的解决方案带来了一个副作用:就是系统不仅增加了新的类Factory,而且当系统移植时,移植工作仅仅是转移到Factory类上,工作量并没有所有缩减,而且还是要修改系统的源码。 从Factory类在系统移植时修改的内容我们能看出: 实际上他是专属于美国企业或中国企业的。名称上应该叫AmericanFactory,ChineseFactory更合适.,解决方案是增加一个抽象工厂类AbstractFactory增加一个静态方法,该方法根据一个设置文件(App.config或Web.config) 一个项(比如factoryName)动态地判断应该实例化哪个工厂类这样,就把移植工作转移到了对设置文件的修改。,using System;using System.Reflection;namespace AbstractFactory/ AbstractFactory类public abstract class AbstractFactorypublic static AbstractFactory GetInstance()string factoryName = Constant.STR_FACTORYNAME.ToString();AbstractFactory instance;if(factoryName = “ChineseFactory”)instance = new ChineseFactory();else if(factoryName = “AmericanFactory”)instance = new AmericanFactory();Elseinstance = n
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026届江苏省苏州市星港学校化学九上期中复习检测模拟试题含解析
- 2026届山东省威海市环翠区化学九年级第一学期期末经典试题含解析
- 2026届福建省厦门六中学九年级化学第一学期期中教学质量检测试题含解析
- 2025版厨柜供货及安装工程合同
- 2025劳动合同法专业培训内容
- 2025标准员工劳动合同范本
- 2025建设工程劳务服务合同
- 2025属公积金贷款签合同注意事项
- 2025版健身办卡协议书合同
- 2025国际贸易采购合同
- 国家电投2023上半年ESG实践报告:绿色发展助力电力行业转型升级
- 中国华电战略发展研究中心招聘笔试题库2025
- 2025呼伦贝尔市交投公路建设有限公司招聘工作人员考试参考试题及答案解析
- 污水处理自动化工程施工组织计划
- 生涯人物访谈表
- 苏教版六年级上数学全册教学反思(全册)
- 地热井常见主要问题分析与研究_图文
- 教育学 德育PPT课件
- 销售业务手册
- 干部任免审批表电子Word
- 保利房地产产品设计标准
评论
0/150
提交评论