zoukankan      html  css  js  c++  java
  • 设计模式-建造者模式

    一、建造者模式概念

    建造者模式是最复杂的创建型模式,它将客户端与包含多个组成部分的复杂对象的创建分离,客户端无需知道复杂对象的内部组成部分与装配模式,只需要知道建造者的类型即可。

    建造者模式关注 该复杂对象 是如何一步步创建而成的。


    二、建造者模式的角色

    1. 产品类:被构建的复杂对象,有好多属性作为组成部件,具体建造者创建该产品的内部组成,表示并定义它的装配过程。
    2. 抽象建造者:创建一个产品对象 供子类设值(装配),一般有两类方法,一类是buildPartX(),子类实现对产品属性的设值,一类是getResult(),用于返回复杂对象。
    3. 具体建造者:实现抽象建造者中的方法,其中各个buildPartX()实现后 即确定了复杂产品的各属性值。也可以提供一个方法返回创建好的复杂产品对象。
    4. 指挥者:又称导演类,负责安排复杂对象的建造次序,指挥者和抽象建造者关联,在construct()建造方法中调用建造者对象的装配方法,完成复杂产品的建造。

    理解:每一个具体建造者类相当于一个具体产品,通过设值装配复杂对象。指挥者里创建抽象建造者对象,当作具体建造者对象使用(设值),然后返回。 建造者里创建产品对象,设值后返回。


     

    三、举例

    KFC如何创建套餐:套餐是一个复杂对象,包含主食(如汉堡、鸡肉卷)和饮料(如果汁、可乐)等组成部分,不同套餐有不同的组成部分,然后KFC服务员根据客户需求一步一步装配套餐,构造出一份完整的套餐,返回给客户。套餐A=汉堡+可乐。套餐B=鸡肉卷+果汁。

    产品类:Meal

    package build;
    
    public class Meal {//产品类,套餐类
        private String food;
        private String drink;
        public String getFood() {
            return food;
        }
        public void setFood(String food) {
            this.food = food;
        }
        public String getDrink() {
            return drink;
        }
        public void setDrink(String drink) {
            this.drink = drink;
        }
    }
    Meal

    抽象建造者MealBuilder 和 具体建造者MealBuilderA、MealBuilderB

    package build;
    
    public abstract class MealBuilder {//抽象套餐,建造者类
        protected Meal meal=new Meal();//这个类对象主要是给子类设值的
        public abstract void buildFood();
        public abstract void buildDrink();
        public Meal getMeal() {
            return meal;
        }
    }
    
    class MealBuilderA extends MealBuilder{//套餐A 具体建造者
        public void buildFood() {
            meal.setFood("汉堡");
        }
        public void buildDrink() {
            meal.setDrink("可乐");
        }
    }
    
    class MealBuilderB extends MealBuilder{//套餐B 具体建造者
        public void buildFood() {
            meal.setFood("鸡肉卷");
        }
        public void buildDrink() {
            meal.setDrink("果汁");
        }
    }
    MealBuilder

    指挥者:KFCWaiter

    package build;
    
    public class KFCWaiter {//指挥者类
        private MealBuilder mb;
        public void setMealBuilder(MealBuilder mb) {
            this.mb=mb;
        }
        public Meal construct() {
            mb.buildFood();
            mb.buildDrink();
            return mb.getMeal();
        }
    }
    KFCWaiter

    模拟DAO:XMLUtil.java和config.xml

    package build;
    
    import javax.xml.parsers.*;
    import org.w3c.dom.*;
    import java.io.*;
    import java.net.URL;
    
    public class XMLUtil {
        
        public static Object getBean() {
            try {
                //创建DOM文档对象
                DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();//文档制造者工厂创建了一个 文档制造者工厂对象
                DocumentBuilder builder=dFactory.newDocumentBuilder();//文档制造者类 通过 文档制造者工厂 创造一个 文档制造者对象
                Document doc;//文档制造者 创建 文档
                doc=builder.parse(new File("src/build/config.xml"));//解析xml文件
                
                //获取包含类名的文本节点
                NodeList nl=doc.getElementsByTagName("className");//文本节点列表里有很多被className标签夹着的内容
                Node classNode=nl.item(0).getFirstChild();
                //item(0)表示引用列表里第一个节点,这里只有一个。getFirstChild表示获取该节点的第一个孩子。
                String cName=classNode.getNodeValue();
    
                //通过类名生成实例对象并返回
                Class c=Class.forName(cName);
                Object obj=c.newInstance();
                return obj;
            }catch(Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    XMLUtil
    <?xml version="1.0"?>
    <config>
        <className>build.MealBuilderA</className>
    </config>
    config.xml

    客户端:Client

    package build;
    
    public class Client {
        public static void main(String[] args) {
            //动态确定套餐种类
            MealBuilder mb=(MealBuilder)XMLUtil.getBean();
            
            //服务员是指挥者
            KFCWaiter waiter=new KFCWaiter();
            
            //服务员准备套餐,这个套餐mb是从XML文件里搞来的一个具体建造者类
            waiter.setMealBuilder(mb);
            
            //客户获得套餐
            Meal meal=waiter.construct();
    
            System.out.println("套餐组成:");
            System.out.println(meal.getFood());
            System.out.println(meal.getDrink());
        }
    
    }
    Client

    四、课后习题

    某游戏软件中任务角色包括多种类型,不同类型的任务角色,其性别、脸型、服装、发型等外部特性有所差异,使用建造者模式创建任务角色对象,要求绘制类图并编程实现。

    妲己:女,锥子脸,咖啡女仆,短发
    甄姬:女,瓜子脸,花好人间,斜刘海
    宫本:男,菱形脸,鬼剑武藏,冲天辫

    产品类

    package homework;
    
    public class Role {//产品类 角色Role
        private String name;
        private String sex;
        private String face;
        private String clothes;
        private String hair;
        public String getSex() {
            return sex;
        }
        public void setSex(String sex) {
            this.sex = sex;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getFace() {
            return face;
        }
        public void setFace(String face) {
            this.face = face;
        }
        public String getClothes() {
            return clothes;
        }
        public void setClothes(String clothes) {
            this.clothes = clothes;
        }
        public String getHair() {
            return hair;
        }
        public void setHair(String hair) {
            this.hair = hair;
        }
    
    }
    Role

    抽象建造者和具体建造者类

    package homework;
    
    public abstract class Rolebuilder {//建造者  角色建造者
    
        protected Role role=new Role(); 
        public abstract void build();
        public Role getRole() {
            return role;
        }
    }
    
    class Daji extends Rolebuilder{//具体建造者  妲己:女,锥子脸,咖啡女仆,短发
        public void build() {
            role.setName("妲己");
            role.setSex("女");
            role.setFace("锥子脸");
            role.setClothes("咖啡女仆");
            role.setHair("短发");
        }
    }
    
    
    class Zhenji extends Rolebuilder{//具体建造者  甄姬:女,瓜子脸,花好人间,斜刘海
        public void build() {
            role.setName("甄姬");
            role.setSex("女");
            role.setFace("瓜子脸");
            role.setClothes("花好人间");
            role.setHair("斜刘海");
        }
    }
    
    class Gongben extends Rolebuilder{//具体建造者  宫本:男,菱形脸,鬼剑武藏,冲天辫
        public void build() {
            role.setName("宫本武藏");
            role.setSex("男");
            role.setFace("菱形脸");
            role.setClothes("鬼剑武藏");
            role.setHair("冲天辫");
        }
    }
    Rolebuilder

    指挥者

    package homework;
    
    public class Player {//指挥者  玩家
        private Rolebuilder rb;
        public void setRolebuilder(Rolebuilder rb) {
            this.rb=rb;
        }
        
        public Role construct() {
            rb.build();
            return rb.getRole();
        }
    }
    Player

    模拟DAO

    package homework;
    
    import javax.xml.parsers.*;
    import org.w3c.dom.*;
    import java.io.*;
    import java.net.URL;
    
    public class XMLUtil {
        
        public static Object getBean() {
            try {
                //创建DOM文档对象
                DocumentBuilderFactory dFactory=DocumentBuilderFactory.newInstance();//文档制造者工厂创建了一个 文档制造者工厂对象
                DocumentBuilder builder=dFactory.newDocumentBuilder();//文档制造者类 通过 文档制造者工厂 创造一个 文档制造者对象
                Document doc;//文档制造者 创建 文档
                doc=builder.parse(new File("src/homework/config.xml"));//解析xml文件
                
                //获取包含类名的文本节点
                NodeList nl=doc.getElementsByTagName("className");//文本节点列表里有很多被className标签夹着的内容
                Node classNode=nl.item(0).getFirstChild();
                //item(0)表示引用列表里第一个节点,这里只有一个。getFirstChild表示获取该节点的第一个孩子。
                String cName=classNode.getNodeValue();
    
                //通过类名生成实例对象并返回
                Class c=Class.forName(cName);
                Object obj=c.newInstance();
                return obj;
            }catch(Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    XMLUtil
    <?xml version="1.0"?>
    <config>
        <className>homework.Zhenji</className>
    </config>
    config.xml

    客户端

    package homework;
    
    public class Client {
        public static void main(String[] args) {
            //从XML文档里知道要做成哪个具体建造者,通过指挥者对象设值、建造、后返回
            Rolebuilder rb=(Rolebuilder)XMLUtil.getBean();
            Player player=new Player();
            player.setRolebuilder(rb);
            Role role=player.construct();
            System.out.println("姓名:"+role.getName());
            System.out.println("性别:"+role.getSex());
            System.out.println("脸型:"+role.getFace());
            System.out.println("服饰:"+role.getClothes());
            System.out.println("发行:"+role.getHair());
        }
    }
    Client
  • 相关阅读:
    js:语言精髓笔记1--标识符与基本类型
    ember.js:使用笔记4 数组数据的分组显示
    ember.js:使用笔记3 活用{{bind-attr}}
    ember.js:使用笔记2-数据删除与存储
    ember.js:使用笔记1-数组数据统一显示
    工具:使用jekyll生成静态网站
    css:删除:×的效果
    js写随机一个颜色
    回调函数的使用
    jquery获取select标签的选中元素
  • 原文地址:https://www.cnblogs.com/shoulinniao/p/11700047.html
Copyright © 2011-2022 走看看