2019-06-09 10:16  阅读(2937)
文章分类:史上最全设计模式 文章标签:设计模式Java 设计模式
©  原文作者:Liuwei-Sunny 原文地址:https://blog.csdn.net/lovelion

作者:Liuwei-Sunny

出处:https://blog.csdn.net/lovelion


8.3 完整解决方案

Sunny公司开发人员决定使用建造者模式来实现游戏角色的创建,其基本结构如图8-3所示:

2019060910035_1.png

图8-3 游戏角色创建结构图

在图8-3中,ActorController充当指挥者,ActorBuilder充当抽象建造者,HeroBuilder、AngelBuilder和DevilBuilder充当具体建造者,Actor充当复杂产品。完整代码如下所示:

//Actor角色类:复杂产品,考虑到代码的可读性,只列出部分成员属性,且成员属性的类型均为String,真实情况下,有些成员属性的类型需自定义classActor{      private Stringtype;//角色类型      private Stringsex;//性别      private Stringface;//脸型      private Stringcostume;//服装      private Stringhairstyle;//发型            public voidsetType(Stringtype){             this.type =type;      }      public voidsetSex(Stringsex){             this.sex =sex;      }      public voidsetFace(Stringface){             this.face =face;      }      public voidsetCostume(Stringcostume){             this.costume =costume;      }      public voidsetHairstyle(Stringhairstyle){             this.hairstyle =hairstyle;      }      public StringgetType(){             return (this.type);      }      public StringgetSex(){             return (this.sex);      }      public StringgetFace(){             return (this.face);      }      public StringgetCostume(){             return (this.costume);      }      public StringgetHairstyle(){             return (this.hairstyle);      }} //角色建造器:抽象建造者abstractclassActorBuilder{      protected Actoractor=newActor();            public abstractvoidbuildType();      public abstractvoidbuildSex();      public abstractvoidbuildFace();      public abstractvoidbuildCostume();      public abstractvoidbuildHairstyle();    //工厂方法,返回一个完整的游戏角色对象      publicActorcreateActor()      {             returnactor;      }} //英雄角色建造器:具体建造者classHeroBuilderextendsActorBuilder{      public voidbuildType()      {             actor.setType("英雄");      }      public voidbuildSex()      {             actor.setSex("男");      }      public voidbuildFace()      {             actor.setFace("英俊");      }      public voidbuildCostume()      {             actor.setCostume("盔甲");      }      public voidbuildHairstyle()      {             actor.setHairstyle("飘逸");      }    } //天使角色建造器:具体建造者classAngelBuilderextendsActorBuilder{      public voidbuildType()      {             actor.setType("天使");      }      public voidbuildSex()      {             actor.setSex("女");      }      public voidbuildFace()      {             actor.setFace("漂亮");      }      public voidbuildCostume()      {             actor.setCostume("白裙");      }      public voidbuildHairstyle()      {             actor.setHairstyle("披肩长发");      }    } //恶魔角色建造器:具体建造者classDevilBuilderextendsActorBuilder{      public voidbuildType()      {             actor.setType("恶魔");      }      public voidbuildSex()      {             actor.setSex("妖");      }      public voidbuildFace()      {             actor.setFace("丑陋");      }      public voidbuildCostume()      {             actor.setCostume("黑衣");      }      public voidbuildHairstyle()      {             actor.setHairstyle("光头");      }    } 
//Actor角色类:复杂产品,考虑到代码的可读性,只列出部分成员属性,且成员属性的类型均为String,真实情况下,有些成员属性的类型需自定义classActor{      private Stringtype;//角色类型      private Stringsex;//性别      private Stringface;//脸型      private Stringcostume;//服装      private Stringhairstyle;//发型            public voidsetType(Stringtype){             this.type =type;      }      public voidsetSex(Stringsex){             this.sex =sex;      }      public voidsetFace(Stringface){             this.face =face;      }      public voidsetCostume(Stringcostume){             this.costume =costume;      }      public voidsetHairstyle(Stringhairstyle){             this.hairstyle =hairstyle;      }      public StringgetType(){             return (this.type);      }      public StringgetSex(){             return (this.sex);      }      public StringgetFace(){             return (this.face);      }      public StringgetCostume(){             return (this.costume);      }      public StringgetHairstyle(){             return (this.hairstyle);      }} //角色建造器:抽象建造者abstractclassActorBuilder{      protected Actoractor=newActor();            public abstractvoidbuildType();      public abstractvoidbuildSex();      public abstractvoidbuildFace();      public abstractvoidbuildCostume();      public abstractvoidbuildHairstyle();    //工厂方法,返回一个完整的游戏角色对象      publicActorcreateActor()      {             returnactor;      }} //英雄角色建造器:具体建造者classHeroBuilderextendsActorBuilder{      public voidbuildType()      {             actor.setType("英雄");      }      public voidbuildSex()      {             actor.setSex("男");      }      public voidbuildFace()      {             actor.setFace("英俊");      }      public voidbuildCostume()      {             actor.setCostume("盔甲");      }      public voidbuildHairstyle()      {             actor.setHairstyle("飘逸");      }    } //天使角色建造器:具体建造者classAngelBuilderextendsActorBuilder{      public voidbuildType()      {             actor.setType("天使");      }      public voidbuildSex()      {             actor.setSex("女");      }      public voidbuildFace()      {             actor.setFace("漂亮");      }      public voidbuildCostume()      {             actor.setCostume("白裙");      }      public voidbuildHairstyle()      {             actor.setHairstyle("披肩长发");      }    } //恶魔角色建造器:具体建造者classDevilBuilderextendsActorBuilder{      public voidbuildType()      {             actor.setType("恶魔");      }      public voidbuildSex()      {             actor.setSex("妖");      }      public voidbuildFace()      {             actor.setFace("丑陋");      }      public voidbuildCostume()      {             actor.setCostume("黑衣");      }      public voidbuildHairstyle()      {             actor.setHairstyle("光头");      }    } 

指挥者类ActorController定义了construct()方法,该方法拥有一个抽象建造者ActorBuilder类型的参数,在该方法内部实现了游戏角色对象的逐步构建,代码如下所示:

//游戏角色创建控制器:指挥者classActorController{   //逐步构建复杂产品对象      publicActorconstruct(ActorBuilderab)      {             Actoractor;             ab.buildType();             ab.buildSex();             ab.buildFace();             ab.buildCostume();             ab.buildHairstyle();             actor=ab.createActor();             returnactor;      }}
//游戏角色创建控制器:指挥者classActorController{   //逐步构建复杂产品对象      publicActorconstruct(ActorBuilderab)      {             Actoractor;             ab.buildType();             ab.buildSex();             ab.buildFace();             ab.buildCostume();             ab.buildHairstyle();             actor=ab.createActor();             returnactor;      }}

为了提高系统的灵活性和可扩展性,我们将具体建造者类的类名存储在配置文件中,并通过工具类XMLUtil来读取配置文件并反射生成对象,XMLUtil类的代码如下所示:

importorg.w3c.dom.;importorg.xml.sax.SAXException;importjava.io.;classXMLUtil{//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象      public staticObjectgetBean()      {             try             {                    //创建文档对象                    DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();                    DocumentBuilder builder=dFactory.newDocumentBuilder();                    Document doc;                                                                    doc =builder.parse(newFile("config.xml"));                                 //获取包含类名的文本节点                    NodeList nl=doc.getElementsByTagName("className");           Node classNode=nl.item(0).getFirstChild();           String cName=classNode.getNodeValue();                      //通过类名生成实例对象并将其返回           Classc=Class.forName(cName);              Objectobj=c.newInstance();           returnobj;        }          catch(Exceptione)        {            e.printStackTrace();            returnnull;        }      }}
importorg.w3c.dom.;importorg.xml.sax.SAXException;importjava.io.;classXMLUtil{//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象      public staticObjectgetBean()      {             try             {                    //创建文档对象                    DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();                    DocumentBuilder builder=dFactory.newDocumentBuilder();                    Document doc;                                                                    doc =builder.parse(newFile("config.xml"));                                 //获取包含类名的文本节点                    NodeList nl=doc.getElementsByTagName("className");           Node classNode=nl.item(0).getFirstChild();           String cName=classNode.getNodeValue();                      //通过类名生成实例对象并将其返回           Classc=Class.forName(cName);              Objectobj=c.newInstance();           returnobj;        }          catch(Exceptione)        {            e.printStackTrace();            returnnull;        }      }}

配置文件config.xml中存储了具体建造者类的类名,代码如下所示:

<?xmlversion="1.0"?><config>      <className>AngelBuilder</className></config>   
<?xmlversion="1.0"?><config>      <className>AngelBuilder</className></config>   

编写如下客户端测试代码:

classClient{      public staticvoidmain(Stringargs[])      {             ActorBuilderab;//针对抽象建造者编程             ab= (ActorBuilder)XMLUtil.getBean();//反射生成具体建造者对象         ActorControllerac=new ActorController();             Actoractor;             actor=ac.construct(ab);//通过指挥者创建完整的建造者对象              String type=actor.getType();             System.out.println(type +"的外观:");             System.out.println("性别:"+actor.getSex());             System.out.println("面容:"+actor.getFace());             System.out.println("服装:"+actor.getCostume());             System.out.println("发型:"+actor.getHairstyle());      }}
classClient{      public staticvoidmain(Stringargs[])      {             ActorBuilderab;//针对抽象建造者编程             ab= (ActorBuilder)XMLUtil.getBean();//反射生成具体建造者对象         ActorControllerac=new ActorController();             Actoractor;             actor=ac.construct(ab);//通过指挥者创建完整的建造者对象              String type=actor.getType();             System.out.println(type +"的外观:");             System.out.println("性别:"+actor.getSex());             System.out.println("面容:"+actor.getFace());             System.out.println("服装:"+actor.getCostume());             System.out.println("发型:"+actor.getHairstyle());      }}

编译并运行程序,输出结果如下:

天使的外观:性别:女面容:漂亮服装:白裙发型:披肩长发
天使的外观:性别:女面容:漂亮服装:白裙发型:披肩长发

在建造者模式中,客户端只需实例化指挥者类,指挥者类针对抽象建造者编程,客户端根据需要传入具体的建造者类型,指挥者将指导具体建造者一步一步构造一个完整的产品(逐步调用具体建造者的buildX()方法),相同的构造过程可以创建完全不同的产品。在游戏角色实例中,如果需要更换角色,只需要修改配置文件,更换具体角色建造者类即可;如果需要增加新角色,可以增加一个新的具体角色建造者类作为抽象角色建造者的子类,再修改配置文件即可,原有代码无须修改,完全符合“开闭原则”。

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> 复杂对象的组装与创建——建造者模式(二):游戏角色设计的建造者模式解决方案
上一篇
复杂对象的组装与创建——建造者模式(一):游戏角色设计,建造者模式概述
下一篇
复杂对象的组装与创建——建造者模式(三):关于Director的进一步讨论,建造者模式总结