设计模式系列之鸣人VS比尔.雷泽

盘置青梅,一樽煮酒,二人对坐,开怀畅饮。操以手指玄德,然后自指曰:“天下英雄,唯使君与操耳”。玄德乃以:“一震之威,乃至于此!”应对。一个长歌当啸,豪气冲天,指点群雄;一个寄人篱下,一味谦恭,装孬不折本。此乃曹刘经典的煮酒论英雄。下面有请我们另外两位英雄——鸣人和比尔.雷泽,这两个二货一见面就唾沫横飞的要大干一场,最终上演了一场不伦不类的模式论英雄的忍术Vs科技之战。

这里不再画建造者模式、抽象工厂模式和方法模式的UML图了,如需要了解的可以去看一下小Y前面的文章建造者模式工厂方法模式抽象工厂模式

一、模式之战第一战—工厂方法模式VS建造者模式

①在工厂方法模式的加持下,直接产生了手持螺旋丸和具备仙人能力的基数庞大的鸣人队伍。
②在建造者模式的控制下,一个个比尔按照预定的顺序生产出各个部分并组装起来。

1.工厂方法模式建造鸣人

①鸣人接口

public interface MingRen {
    //鸣人的技能
    void getAbility();
}

②手持螺旋丸的鸣人

public class MingRenOfSpiral implements MingRen {

    @Override
    public void getAbility() {
        System.out.println("手持螺旋丸的鸣人。");
    }
}

③仙人模式的鸣人

public class MingRenOfFairy implements MingRen {

    @Override
    public void getAbility() {
        System.out.println("仙人模式的鸣人。");
    }
}

④抽象鸣人制造工厂

public abstract class AbstractMingRenFactory {
    public abstract <T extends MingRen> T createMingRen(Class<T> c);
}

⑤鸣人制造工厂

public class MingRenFactory extends AbstractMingRenFactory {
    //定义一个要生产的鸣人
    private MingRen mingRen;
    @Override
    public <T extends MingRen> T createMingRen(Class<T> c) {
        try {
            //生产鸣人
            mingRen= (MingRen) Class.forName(c.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return (T) mingRen;
    }
}

⑥生产鸣人

public class Client {

    public static void main(String []args){
        //声明一个鸣人制造工厂
        AbstractMingRenFactory mingRenFactory=new MingRenFactory();
        //制造一个螺旋丸的鸣人
        MingRenOfSpiral mingRenOfSpiral=mingRenFactory.createMingRen(MingRenOfSpiral.class);
        mingRenOfFairy.getAbility();

        //制造一个仙人模式的鸣人
        MingRenOfFairy mingRenOfFairy=mingRenFactory.createMingRen(MingRenOfFairy.class);
        mingRenOfFairy.getAbility();
        
    
    }
}

鸣人制造工厂能够源源不断地生产出手持螺旋丸和进入仙人模式的鸣人,工厂方法模式主要的目的是能够直接产生一个新的鸣人,具体是手持螺旋丸还是仙人模式的鸣人,则由客户端决定。也就是说具体怎么生产、怎么组装,这不是工厂方法模式考虑的,工厂方法模式关注的是一个产品的整体。

2.建造法模式建造比尔雷泽

①生产一个比尔需要的部分,即产品

public class Bizzer {
    //比尔的身体
    private String body;
    //比尔的雪茄
    private String cigar;
    //比尔的武器
    private String arms;


    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getCigar() {
        return cigar;
    }

    public void setCigar(String cigar) {
        this.cigar = cigar;
    }

    public String getArms() {
        return arms;
    }

    public void setArms(String arms) {
        this.arms = arms;
    }
}

比尔雷雷泽简化为三个部分:身体、雪茄、武器。

②抽象建造者

public abstract class Builder {
    protected Bizzer bizzer=new Bizzer();
    //构建比尔身体
    public void setBody(String body){
        this.bizzer.setBody(body);
    }
    //构建比尔的雪茄
    public void setCigar(String cigar){
        this.bizzer.setCigar(cigar);
    }
    //构建比尔的武器
    public void setArms(String arms) {
        this.bizzer.setArms(arms);
    }

    //得到完整的比尔
    public abstract Bizzer getBizzer();
}

比尔的组成部分上面都已经知道了,具体怎么组装就由实现类决定。

③装备散弹枪的比尔

public class BizzerOneBuilder extends Builder {
    @Override
    public Bizzer getBizzer() {
        super.setBody("强壮的身躯");
        super.setArms("92年的雪茄");
        super.setArms("装备散弹枪");
        return super.bizzer;
    }
}

④装备加特林的比尔

public class BizzerTwoBuilder extends Builder {
    @Override
    public Bizzer getBizzer() {
        super.setBody("强壮的身躯");
        super.setArms("92年的雪茄");
        super.setArms("装备加特林");
        return super.bizzer;
    }
}

上面两个具体的建造者,它们都关注了各个部分,它们的主要目的是通过不同的部件,不同的装配产生不同的复杂对象,最主要的是关心产品的构建顺序。

⑤导演类

public class Director {
    //装备散弹枪比尔建造者
    private static Builder bizzerOneBuilder=new BizzerOneBuilder();
    //装备加特林比尔建造者
    private static Builder bizzerTwaoBuilder=new BizzerTwoBuilder();

    public static Bizzer getOneBizzer(){
        return bizzerOneBuilder.getBizzer();
    }
    public static Bizzer getTwoBizzer(){
        return bizzerTwaoBuilder.getBizzer();
    }
}

⑥生产比尔雷泽

public class Client {
    public static void main(String[] args){
        //建造一个手持散弹枪的比尔
        Bizzer bizzerOne=Director.getOneBizzer();
        //建造一个手持加特林的比尔
        Bizzer bizzerTwo=Director.getTwoBizzer();
    }
}

3.两者的共同点和区别

共同点

工厂方法模式和建造者模式都属于创建类模式,都是用来创建对象。

区别

  • 产品的复杂度不同
    工厂方法模式创建的产品一般都是单一性质产品。而建造者模式创建的是一个复合产品,它由各个部件复合组成,部件不同产品对象当然也不同。

  • 主要目的不同
    工厂方法模式关注的是一个整体,无须关心产品各部分是如何创建出来的;但在建造者模式中,一个产品的产生是依赖各个部件以及装配的顺序,即是关注产品组成部分的创建过程。

二、模式之战第二战—抽象工厂模式VS建造者模式

忍术VS科技第一战比尔雷泽占了明显的优势,在比拼过程中鸣人的优势是可以快速生产出基数庞大的鸣人群,对比尔进行数量上的压制;但是比尔这货优势在于注重组装的细节,每个部分都精细化生产,战斗力也是不可比拟的,加上强武器的加持,鸣人大军的正在节节败退。鸣人怎么说都是一代枭雄,怎会没有一两个压箱底的绝招呢,只见他口念咒语、手结手印,更加庞大的加强版的鸣人军蜂拥而至,重新形成了相抗衡的局面。

1.鸣人的绝招-抽象工厂模式

按照抽象工厂模式,先定义一个鸣人接口,然后仙人模式的鸣人和九喇嘛模式的鸣人都实现鸣人接口,我们从产品等级和产品族去分析,仙人模式和九喇嘛模式属于同一个产品等级(有N个产品等级就应该有N个实现工厂),仙人模式和九喇嘛模式下面又可以会螺旋丸的和会鸣人连弹的(N个产品族,在抽象工厂类中就要有N个创建方法)。

①鸣人接口

public interface MingRen {
    //鸣人的技能
    void getAbility();
}

②仙人模式的会连弹的鸣人

public class FairyModeOfMingRenBomb implements MingRen{
    @Override
    public void getAbility() {
        System.out.println("仙人模式的会连弹的鸣人");
    }
}

③仙人模式的会旋螺丸的鸣人

public class FairyModeOfMingRenSpiral implements MingRen{
    @Override
    public void getAbility() {
        System.out.println("仙人模式的会旋螺丸的鸣人");
    }
}

④九喇嘛模式的会连弹的鸣人

public class NineLamaOfMingRenBomb implements MingRen{
    @Override
    public void getAbility() {
        System.out.println("九喇嘛模式的会连弹的鸣人");
    }
}

⑤九喇嘛模式的会旋螺丸的鸣人

public class NineLamaOfMingRenSpiral implements MingRen{
    @Override
    public void getAbility() {
        System.out.println("九喇嘛模式的会旋螺丸的鸣人");
    }
}

⑦抽象工厂

public interface MingRenFactory {
    //创建会连弹的鸣人
    public MingRen createMingRenBomb();
    //创建会旋螺丸的鸣人
    public MingRen createMingRenSpiral();
}

⑧仙人模式鸣人工厂

public class FairyModeMingRenFactory implements MingRenFactory {

    @Override
    public MingRen createMingRenBomb() {
        return new FairyModeOfMingRenBomb();
    }

    @Override
    public MingRen createMingRenSpiral() {
        return new FairyModeOfMingRenSpiral();
    }
}

⑨九喇嘛模式鸣人工厂

public class NineLamaMingRenFactory implements MingRenFactory {

    @Override
    public MingRen createMingRenBomb() {
        return new NineLamaOfMingRenBomb();
    }

    @Override
    public MingRen createMingRenSpiral() {
        return new NineLamaOfMingRenSpiral();
    }
}

⑩开始生产鸣人

public class Client {

    public static void main(String[] args){
        //分别生产一个仙人模式下的会连弹和会旋螺丸的鸣人
        FairyModeMingRenFactory fairyModeMingRenFactory=new FairyModeMingRenFactory();
        MingRen mingRenOne=fairyModeMingRenFactory.createMingRenBomb();
        mingRenOne.getAbility();
        MingRen mingRenTwo=fairyModeMingRenFactory.createMingRenSpiral();
        mingRenTwo.getAbility();
    }
}

抽象工厂模式页注重完整性,一个产品一旦找到一个工厂生产,那就会生产出一个固定的产品,这样子鸣人的加强版大军很快就被生产出来了。

2.抽象工厂和建造者模式的区别

  • 抽象工厂模式是工厂方法模式的升级版,前面也说了,抽象工厂模式关注产品的整体,而建造者模式则关注构建的过程,两者的场景因此也大不相同,如果希望屏蔽对象的创建过程,只提供一个封装良好的对象,则可以选择抽象工厂模式;如果通过转配不同的组件和构建的顺序可以产生一个新的对象,同时建造者模式创建的是一个复合产品,它由各个部件复合组成。

三、拓展之战—抽象工厂模式VS工厂方法模式

工厂创建一种产品,抽象工厂创建的是一组产品,是一个产品系列。这里要注意的是“系列”的意思,也就是说,抽象工厂创建出的一组产品是成套的。
当有一个接口可以有多种实现的时候,可以考虑使用工厂方法来创建实例。
当有一组接口可以有多种实现方案的时候,可以考虑使用抽象工厂创建实例组。

推荐阅读更多精彩内容