建造者模式
Posted remote
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了建造者模式相关的知识,希望对你有一定的参考价值。
场景引入:无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮、方向盘、发送机等各种部件。而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象。用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节.
定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
建造者模式是一种对象创建型模式,他将客户端与包含多个部件的复杂对象的创建过程分离,客户端无需知道复杂对象的内部组成部分与装配方式,只需知道所建造者的类型即可。
建造者模式结构图
由上图可知,建造者模式包含以下4个角色
(1)Builder(抽象建造者):它为创建产品对象的各个部件指定抽象借口,在该接口中一般声明两种方法:一类方法是buildPartX(),它们用于创建复杂对象的各个部件;另一类方法是getResult(),它们用于返回复杂对象。Builder既可以是抽象类,也可以是接口
(2)ConcreteBuilder(具体建造者):它实现了Builder接口,实现各个部件的具体构造和装配方法,定义并明确所创建的复杂对象,还可以提供一个返回创建好的复杂产品对象
(3)Product(产品):它是被构建的复杂对象,包含多个组成部件,具体建造者创建该产品的内部表示并定义它的装配过程
(4)Director(指挥者):构建一个使用Builder接口的对象。它主要是用于创建一个复杂的对象。它主要有两个作用,一是:隔离了客户与对象的生产过程,二是:负责控制产品对象的生产过程。
建造者模式应用实例
1. 实例说明
某游戏软件公司决定开发一款基于角色扮演的多人在线网络游戏,玩家可以在游戏中扮演虚拟世界中的一个特定角色,角色根据不同的游戏情节和统计数据(例如力量、魔法、技能等)具有不同的能力,角色也会随着不断升级而拥有更加强大的能力。作为该游戏的一个重要组成部分,而且随着该游戏的升级将不断增加新的角色。通过分析发现,游戏角色是一个复杂对象,它包含性别、脸型等多个组成部分,不同类型的游戏角色,其性别、脸型、服装、发型等外部特征都有所差异,例如“天使”拥有美丽的面容和披肩长发,并身着一袭白裙;而“恶魔”极其丑陋,留着光头并穿着一件刺眼的黑衣。
2. 实例类图
3. 实例代码
1 package designpatterns.builder; 2 3 public class Actor { 4 private String type; //角色类型 5 private String sex; //性别 6 private String face; //脸型 7 private String costume; //服装 8 private String hairstyle; //发型 9 public String getType() { 10 return type; 11 } 12 public String getSex() { 13 return sex; 14 } 15 public String getFace() { 16 return face; 17 } 18 public String getCostume() { 19 return costume; 20 } 21 public String getHairstyle() { 22 return hairstyle; 23 } 24 public void setType(String type) { 25 this.type = type; 26 } 27 public void setSex(String sex) { 28 this.sex = sex; 29 } 30 public void setFace(String face) { 31 this.face = face; 32 } 33 public void setCostume(String costume) { 34 this.costume = costume; 35 } 36 public void setHairstyle(String hairstyle) { 37 this.hairstyle = hairstyle; 38 } 39 }
1 package designpatterns.builder; 2 3 public abstract class ActorBuilder { 4 protected Actor actor = new Actor(); 5 6 public abstract void buildType(); 7 public abstract void buildSex(); 8 public abstract void buildFace(); 9 public abstract void buildCostume(); 10 public abstract void buildHairstyle(); 11 12 public Actor createActor(){ 13 return actor; 14 } 15 }
1 package designpatterns.builder; 2 3 public class HeroBuilder extends ActorBuilder { 4 5 @Override 6 public void buildType() { 7 actor.setType("英雄"); 8 } 9 10 @Override 11 public void buildSex() { 12 actor.setSex("男"); 13 } 14 15 @Override 16 public void buildFace() { 17 actor.setFace("英俊"); 18 } 19 20 @Override 21 public void buildCostume() { 22 actor.setCostume("盔甲"); 23 } 24 25 @Override 26 public void buildHairstyle() { 27 actor.setHairstyle("飘逸"); 28 } 29 30 }
1 package designpatterns.builder; 2 3 public class AngelBuilder extends ActorBuilder { 4 5 @Override 6 public void buildType() { 7 actor.setType("天使"); 8 } 9 10 @Override 11 public void buildSex() { 12 actor.setSex("女"); 13 } 14 15 @Override 16 public void buildFace() { 17 actor.setFace("漂亮"); 18 } 19 20 @Override 21 public void buildCostume() { 22 actor.setCostume("白裙"); 23 } 24 25 @Override 26 public void buildHairstyle() { 27 actor.setHairstyle("披肩长发"); 28 } 29 30 }
1 package designpatterns.builder; 2 3 public class DevilBuilder extends ActorBuilder { 4 5 @Override 6 public void buildType() { 7 actor.setType("恶魔"); 8 } 9 10 @Override 11 public void buildSex() { 12 actor.setSex("妖"); 13 } 14 15 @Override 16 public void buildFace() { 17 actor.setFace("丑陋"); 18 } 19 20 @Override 21 public void buildCostume() { 22 actor.setCostume("黑衣"); 23 } 24 25 @Override 26 public void buildHairstyle() { 27 actor.setHairstyle("光头"); 28 } 29 30 }
1 package designpatterns.builder; 2 3 public class ActorController { 4 public Actor construct(ActorBuilder ab){ 5 Actor actor; 6 ab.buildType(); 7 ab.buildSex(); 8 ab.buildFace(); 9 ab.buildCostume(); 10 ab.buildHairstyle(); 11 actor = ab.createActor(); 12 return actor; 13 } 14 }
1 <?xml version="1.0"?> 2 <config> 3 <className>designpatterns.builder.AngelBuilder</className> 4 </config>
1 package designpatterns.builder; 2 3 import java.io.File; 4 import javax.xml.parsers.*; 5 import org.w3c.dom.*; 6 7 public class XMLUtil { 8 public static Object getBean() { 9 try { 10 //创建DOM文件对象 11 DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); 12 DocumentBuilder builder = dFactory.newDocumentBuilder(); 13 Document doc; 14 doc = builder.parse(new File("src//designpatterns//builder//config.xml")); 15 16 //获取包含类名的文本节点 17 NodeList nList = doc.getElementsByTagName("className"); 18 Node classNode = nList.item(0).getFirstChild(); 19 String cName = classNode.getNodeValue(); 20 21 //通过类名生成实例对象并将其返回 22 Class c = Class.forName(cName); 23 Object obj = c.newInstance(); 24 return obj; 25 } catch (Exception e) { 26 e.printStackTrace(); 27 return null; 28 } 29 } 30 }
1 package designpatterns.builder; 2 3 public class Client { 4 5 public static void main(String[] args) { 6 ActorBuilder ab; 7 ab = (ActorBuilder)XMLUtil.getBean(); 8 9 ActorController ac = new ActorController(); 10 11 Actor actor; 12 actor = ac.construct(ab); 13 14 System.out.println(actor.getType() + "的外观:"); 15 System.out.println("性别:" + actor.getSex()); 16 System.out.println("面容:" + actor.getFace()); 17 System.out.println("服装:" + actor.getCostume()); 18 System.out.println("发型:" + actor.getHairstyle()); 19 } 20 21 }
4. 结果及分析
当需要增加新的具体角色建造者时只需将新增具体角色建造者作为抽象角色建造者的子类,然后修改配置文件,原有的代码无需修改,完全符合开闭原则
以上是关于建造者模式的主要内容,如果未能解决你的问题,请参考以下文章