设计模式:建造者模式学习---创建英雄

2018-08-16  本文已影响14人  冰封的鸢尾花

ps:android 中的设计模式:https://www.jianshu.com/p/1a9f571ad7c0

建造者模式,是指在创建一个复杂类型对象时,将创建过程和它的组成(表示)分离,使得同样的构建过程可以创建不同的表示。

在实际的开发中,有时候我们在创建对象的时候发现这个对象有很多的参数,为了涵盖所有的创建的模式,这个类需要包含每个参数的构造方法。比如:

public class TheObject(){

    private int o1;
    private int o2;
    private int o3;
    publiv TheObject(int o1){
    this.o1=o1;
    }   
    publiv TheObject(int o1,o2){
    this.o1=o1;
    this.o2=o2;
    }
    publiv TheObject(int o1,int o2,int o3){
    this.o1=o1;
    this.o2=o2;
    this.o3=o3;
    }
}

这里方法并没有定义完全,但是可以看到仅有三个变量,构造方法已经显得臃肿起来。当我们需要定义的参数更多,定义的方法更加复杂的时候,这会导致代码很难写,也很难阅读,而且在进行多线程编程的时候,例如在两个不同的线程中对同一个变量调用构造方法进行不同的实例化,由于线程执行的特性,会导致一些问题。

此时,构造者模式提供了一个解决这个问题的方法。

ps:显然之前的方法要比建造者模式容易理解,在平时编程也经常用之前的方法。

回顾一下建造者模式的概念:将一个复杂概念的创建过程和它的组成分离,那么意味着可以将创建过程写成接口,创建一个生产者,实现这些创建过程。而具体获得某种对象时,需要在指导者对象中具体调用相应的方法。下面通过一个实例来演示这个过程。

例子:创建英雄的过程 1.生产对象的描述:英雄们所拥有的属性有:生命值(HP),魔法值(SP),能量(Chakra),攻击力(Attack),法术强度(Magic),护甲值(Shell),魔法抗性(Magres),移动速度(Speed) 2.实际生产描述:在实际的英雄属性中,有的英雄没有魔法值,有的英雄没有魔法抗性,有的英雄有法术强度等情况,所以可以用建造者模式来实现英雄创建的功能。 3.需要创建的对象:英雄对象(class),构建方法(build 接口)其中有对应的构造方法,

英雄属性描述对象:

public class Hero{
    private float hp;//血量
    private float sp;//魔法值
    private float chakra;//能量
    private float attack;//攻击力
    private float magic;//法术强度
    private float shell;//护甲值
    private float magres;//魔法抗性
    private float speed;//移动速度

    //get和set方法省略
}

这里包含了所有英雄会有的属性。但其实这些属性在我们创建英雄时并不会全部用到。如果按照老的方法,要包含所有的构造可能性,需要重载许多个构造方法。但是我们采用构造者模式,则会使过程简单,使用方便。

接下来我们创建一个包含建造方法的接口:

public interface Builder {

    /*
     * 包含了产品 创建过程和返回产品的方法
     */
    public Builder BuildHp(float hp);
    public Builder BuildSp(float sp);
    public Builder BuildChakra(float chakra);
    public Builder BuildAttack(float attack);
    public Builder BuildMagic(float magic);
    public Builder BuildShell(float shell);
    public Builder BuildMagRes(float magRes);
    public Builder BuildSpeed(float speed);

    public Hero CreatHero();

}

其中包含了每个属性的建造方法,还包含了一个英雄创建方法。

现在英雄对象和创建方法都有了,接下来我们要创建一个生产者来实现这些建造方法

public class HeroGenerator implements Builder {
    Hero theHero;
    private float hp = 0;// 血量
    private float sp = 0;// 魔法值
    private float chakra = 0;// 能量
    private float attack = 0;// 攻击力
    private float magic = 0;// 法术强度
    private float shell = 0;// 护甲值
    private float magRes = 0;// 魔法抗性
    private float speed = 0;// 移动速度

    private static class SingletonHoder {
        private static final HeroGenerator generator = new HeroGenerator();
    }

    private HeroGenerator() {
        theHero = new Hero();
    }

    public static final HeroGenerator getInstance() {
        return SingletonHoder.generator;
    }

    @Override
    public Builder BuildHp(float hp) {
        // TODO Auto-generated method stub
        this.hp = hp;
        logger.info("生命值:" + hp);
        //System.out.println("生命值:" + hp);
        return this;
    }

    @Override
    public Builder BuildSp(float sp) {
        // TODO Auto-generated method stub
        this.sp = sp;
        logger.info("魔法值:" + sp);
        //System.out.println("魔法值:" + sp);
        return this;
    }

    @Override
    public Builder BuildChakra(float chakra) {
        // TODO Auto-generated method stub
        this.chakra = chakra;
        //System.out.println("能量值:" + chakra);
        logger.info("能量值:" + chakra);
        return this;
    }

    @Override
    public Builder BuildAttack(float attack) {
        // TODO Auto-generated method stub
        this.attack = attack;
        //System.out.println("攻击力:" + attack);
        logger.info("攻击力:" + attack);
        return this;
    }

    @Override
    public Builder BuildMagic(float magic) {
        // TODO Auto-generated method stub
        this.magic = magic;
        //System.out.println("法术强度:" + magic);
        logger.info("法术强度:" + magic);
        return this;
    }

    @Override
    public Builder BuildShell(float shell) {
        // TODO Auto-generated method stub
        this.shell = shell;
        //System.out.println("法术强度:" + magic);
        logger.info("法术强度:" + magic);
        return this;
    }

    @Override
    public Builder BuildMagRes(float magRes) {
        // TODO Auto-generated method stub
        this.magRes = magRes;
        //System.out.println("魔抗:" + magRes);
        logger.info("魔抗:" + magRes);
        return this;
    }

    @Override
    public Builder BuildSpeed(float speed) {
        // TODO Auto-generated method stub
        this.speed = speed;
        //System.out.println("移动速度:" + speed);
        logger.info("移动速度:" + speed);
        return this;
    }

    @Override
    public Hero CreatHero() {
        // TODO Auto-generated method stub
        theHero.setHp(hp);
        theHero.setSp(sp);
        theHero.setChakra(chakra);
        theHero.setAttack(attack);
        theHero.setMagic(magic);
        theHero.setShell(shell);
        theHero.setMagRes(magRes);
        theHero.setSpeed(speed);

        return this.theHero;
    }
}

在这个建造者类中,采用了单例模式来包装建造者的构造方法,关于单例模式,请看《Hi,我们再来聊一聊Java的单例吧》

实现构造方法的写法思想来源自《Effective Java 第二版》的第二条:遇到多个构造器参数是要考虑用构造器。在每个build方法中返回当前对象this,这种写法有个好处是可以将所有的调用链接起来,使得代码容易编写。

好了,现在我们就可以创建英雄了。现在请设计师出场,来设计每个英雄的属性。

public class Director {

    private HeroGenerator generator;

    public Director(HeroGenerator generator){
        this.generator = generator;
    }
    //创建卡特琳娜
    public Hero SommonKaterina() {

        System.out.println("召唤卡特琳娜");
        return generator.BuildHp(450).BuildAttack(55).BuildShell(25).BuildMagRes(27)
                .BuildSpeed(355).CreatHero();
    }
    //创建盖伦
    public Hero SommonGalen(){
        System.out.println("召唤盖伦");
        return generator.BuildHp(550).BuildAttack(68).BuildShell(33).BuildMagRes(36)
                .BuildSpeed(340).CreatHero();
    }
    //创建皇子
    public Hero SommonGarven(){
        System.out.println("召唤皇子");
        return generator.BuildHp(500).BuildSp(350).BuildAttack(68).BuildShell(31)
                .BuildMagRes(35).BuildSpeed(345).CreatHero();
    }
    //创建霞
    public Hero SommoXia(){
        System.out.println("召唤霞");
        return generator.BuildHp(450).BuildSp(400).BuildAttack(65).BuildShell(25).BuildMagRes(27)
                .BuildSpeed(350).CreatHero();
    }
    //创建洛
    public Hero SommoLuo(){
        System.out.println("召唤洛");
        return generator.BuildHp(500).BuildSp(375).BuildAttack(60).BuildShell(27).BuildMagRes(30)
                .BuildSpeed(350).CreatHero();
    }
}

这样构造,会使得代码编写十分方便整洁,而且十分灵活。

我们在召唤这些英雄中,只需要调用这个类型中的具体方法中就可以了,非常方便。

public class SummonerCanyon {

    static Logger logger = Logger.getLogger(SummonerCanyon.class);
    public  HeroGenerator generator;
    public  Director director;

    }

    public void SummoneHeros() {

        PropertyConfigurator.configure("../createHero/src/log4j.xml");
        logger.setLevel(Level.INFO);
        logger.info("召唤英雄");
        //用静态方式访问改静态方法
        generator = HeroGenerator.getInstance();
        director = new Director(generator);
        director.SommonGalen();
        director.SommonGarven();
        director.SommonKaterina();
        director.SommoXia();
        director.SommoLuo();

    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SummonerCanyon canyon = new SummonerCanyon();
        canyon.SummoneHeros();
    }

点击运行,输出结果为(这里我采用了log4j日志来输出结果)

2018-07-13 12:06:44,017 INFO  com.createHero.SummonerCanyon.SummoneHeros:42 - 召唤英雄
召唤盖伦
2018-07-13 12:06:44,021 INFO  com.createHero.base.HeroGenerator.BuildHp:38 - 生命值:550.0
2018-07-13 12:06:44,021 INFO  com.createHero.base.HeroGenerator.BuildAttack:66 - 攻击力:68.0
2018-07-13 12:06:44,024 INFO  com.createHero.base.HeroGenerator.BuildShell:84 - 护甲值:33.0
2018-07-13 12:06:44,024 INFO  com.createHero.base.HeroGenerator.BuildMagRes:94 - 魔抗:36.0
2018-07-13 12:06:44,024 INFO  com.createHero.base.HeroGenerator.BuildSpeed:103 - 移动速度:340.0
召唤皇子
2018-07-13 12:06:44,024 INFO  com.createHero.base.HeroGenerator.BuildHp:38 - 生命值:500.0
2018-07-13 12:06:44,024 INFO  com.createHero.base.HeroGenerator.BuildSp:47 - 魔法值:350.0
2018-07-13 12:06:44,025 INFO  com.createHero.base.HeroGenerator.BuildAttack:66 - 攻击力:68.0
2018-07-13 12:06:44,025 INFO  com.createHero.base.HeroGenerator.BuildShell:84 - 护甲值:31.0
2018-07-13 12:06:44,025 INFO  com.createHero.base.HeroGenerator.BuildMagRes:94 - 魔抗:35.0
2018-07-13 12:06:44,025 INFO  com.createHero.base.HeroGenerator.BuildSpeed:103 - 移动速度:345.0
召唤卡特琳娜
2018-07-13 12:06:44,025 INFO  com.createHero.base.HeroGenerator.BuildHp:38 - 生命值:450.0
2018-07-13 12:06:44,025 INFO  com.createHero.base.HeroGenerator.BuildAttack:66 - 攻击力:55.0
2018-07-13 12:06:44,025 INFO  com.createHero.base.HeroGenerator.BuildShell:84 - 护甲值:25.0
2018-07-13 12:06:44,027 INFO  com.createHero.base.HeroGenerator.BuildMagRes:94 - 魔抗:27.0
2018-07-13 12:06:44,027 INFO  com.createHero.base.HeroGenerator.BuildSpeed:103 - 移动速度:355.0
召唤霞
2018-07-13 12:06:44,027 INFO  com.createHero.base.HeroGenerator.BuildHp:38 - 生命值:450.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildSp:47 - 魔法值:400.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildAttack:66 - 攻击力:65.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildShell:84 - 护甲值:25.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildMagRes:94 - 魔抗:27.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildSpeed:103 - 移动速度:350.0
召唤洛
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildHp:38 - 生命值:500.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildSp:47 - 魔法值:375.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildAttack:66 - 攻击力:60.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildShell:84 - 护甲值:27.0
2018-07-13 12:06:44,028 INFO  com.createHero.base.HeroGenerator.BuildMagRes:94 - 魔抗:30.0
2018-07-13 12:06:44,029 INFO  com.createHero.base.HeroGenerator.BuildSpeed:103 - 移动速度:350.0
上一篇下一篇

猜你喜欢

热点阅读