随着游戏的发展,人族有了更多的资源,有了机械工厂,可以制造更多的兵种(坦克,巨人车……),如果此时还用简单工厂的模式就要修改训练工厂,加入更多的if:

if(gas<25)

{return new Marine();}

else if(gas<50)  

{return new Firebat();}

else if(gas<100)

{return new Goliath();}

else if

……

这样就整个程序就对训练工厂过分依赖,不符合OO思想,不是我们所希望了,于是我们对简单工厂做了一些扩展!训练工厂改名了,叫训练部,它不再参与具体的兵种训练,只负责颁发某些规定、准则,程序里我们称为抽象工厂,游戏里该部门宣布所有下级部门有一个共同的任务:训练部队。具体的部队训练交给了训练部的下级部门:人力部队训练营(训练人力兵种),机械部队生产部(生产机械兵种),这两个部门在程序里我们称为具体工厂。现在我们在看看训练出来的部队,不管是人力部队训练营还是机械部队生产部只有训练出合格的部队才算成功,训练部对合格的部队作了规定,1,必须具备对抗还击的技能,2训练结束后马上到前线报道。这个在程序中我们叫抽象产品,他只提供一个标准或接口,具体到相应部队,人力兵,必须具备使用射击技能,训练后到前线司令部报道。机械兵种必须能够自动开火,可以维修,生产结束后送到前线武装部。这在程序里叫具体产品。


好了,现在我们看看程序



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

namespace starcraft.FactoryMethod
{
    public abstract class TrainDepartment  //训练部,只负责指定部门纪律及任务,抽象工厂角色
    
{
        public abstract Army train();  //下级所有部门都要进行训练部队任务 
    }

    public class BarracksFactory:TrainDepartment   //人力部队训练营,具体工厂角色
    
{
        public override Army train()
        
{
            return new BarracksArmy();   //训练人力兵种,即机枪兵或喷火兵         
        }
    }

    public class MachineFactory : TrainDepartment   //机械部队生产部,具体工厂角色
    
{
        public override Army train()
        
{
            return new MachineArmy();   //生产机械兵种,即坦克或巨人车
        }
    }

    public abstract class Army   //规定训练部队合格的标准及任务, 抽象产品角色
    
{
        public abstract void check(); //开始训练并进行合格检查
        protected abstract void rallyPoint();  //所有新训练出来的部队立即到指定地点where集合,游戏里通过“R”来聚兵
    }
    public class BarracksArmy : Army   //人力兵, 具体产品角色
    
{
        public override void check()
        
{
            string skill = "会射击";   //人力兵需要的技能
            Console.Write("训练了一个枪兵,{0}。",skill);
            rallyPoint();
            Console.WriteLine("");
        }        
        protected override void rallyPoint()
        
{
            Console.Write("已经到司令部部门报道了,投入战斗。");
        }
    }
    public class MachineArmy : Army   //机械部队, 具体产品角色
    
{
        public override void check()
        
{
            string skill = "能开火,可以修理";   //机械兵需要的技能
            Console.Write("生产出一个坦克,{0}。", skill);
            rallyPoint();
            Console.WriteLine("");
        }
        protected override void rallyPoint()
        
{
            Console.Write("送到武装部,投入战斗。");
        }
    }
    
    class game                //一个具体的游戏
    
{

        private static void trainRequest(TrainDepartment factory, int n)
        
{
            for (int i = 0; i < n; i++)
            
{
                factory.train().check();
            }
        }
        static void Main(string[] args)
        
{
            Console.WriteLine("根据局面形势,需要3个枪兵");
            trainRequest(new BarracksFactory(), 3);  //向训练不发出训练3个枪兵的需求,要求练兵
            
            Console.WriteLine("根据形势变化,需要3个坦克");
            trainRequest(new MachineFactory(), 3);   //向训练不发出训练3个坦克的需求,要求生产
            //根据需求的变化我们只需要修改此处的工厂类,而无需修改那n个产品类。         
        }
    }
}
 

 

 注意看game中的trainRequest方法,他代表了在一个具体的项目里,建造具体的产品的机会会很多,遍布在程序的不同角落,那时不是一个简单的循环就可以搞定,按照传统方法,需要使用很多RarracksArmy ra=new RarracksArmy(),如果需求变了,比如现在不需要枪兵了,需要坦克,就要把所有的RarracksArmy ra=new RarracksArmy()修改为MachineArmy ra=new MachineArmy();修改量必然很大,而引进工厂方法后就不用修改所有的产品,只需须改工厂类TrainDepartment factory = new MachineFactory();,这样可以将修改量减少到最小!


运行结果:



 人族正在紧张的生产着,部队源源不断的训练出来,应聚集在前沿阵地,此时一件意想不到的事情发生了,神族秘密的空降了2个金甲虫在人族基地,人族得scv开始逃亡,逃亡得过程中被击中,死伤大半,等scv到达安全位置后,坦克部队回来了,可坦克刚刚展开神族金甲虫已经返回运输机,这是人族隐性战机回来支援,可等战机回来时,神族运输机已经消失的无影无踪!(真是一个菜鸟的操作啊,