[设计模式]建造者模式

开始写设计模式系列,希望自己可以坚持下来.
第二篇:建造者模式

什么是建造者模式

建造者模式是一步一步创建一个复杂对象,允许用户不了解细节的情况下精细的控制对象的构造过程。使得复杂对象的构建与他的表示相分离,同样的构造过程可以创建不同的表示。

经典模式

在生活中我们经常买票,各种各样的票,我们这里要创建一个可以售卖多种票的程序。
首先是产品Product,他是一个抽象类,他有各种票都有的特征,以及票在购买当中会经历的状态,check,检测这张票的信息是否可靠(如生成时间,设备,渠道等),pay,对这张票进行支付,query,查询这张票的支付状态(如,金额是否一致等)

package top.huyuxin.builder;

public abstract class Ticket {
    protected String ticketname;
    protected boolean isCheck=false;
    protected boolean isPayed=false;
    protected boolean isQuery=false;

    public Ticket() {
        super();
    }

    public abstract void  setTicketname();

    public void setCheck(boolean isCheck) {
        this.isCheck = isCheck;
    }

    public void setPayed(boolean isPayed) {
        this.isPayed = isPayed;
    }

    public boolean isQuery() {
        return isQuery;
    }

    public void setQuery(boolean isQuery) {
        this.isQuery = isQuery;
    }

    @Override
    public String toString() {
        return "Ticket [ticketname=" + ticketname + ", isCheck=" + isCheck + ", isPayed=" + isPayed + ", isQuery="
                + isQuery + "]";
    }

}

现在这个程序出售两种票,一种火车票,一种汽车票

package top.huyuxin.builder;
/**
*火车票
**/
public class TrainTicket extends Ticket {


    public TrainTicket() {
        super();
    }

    @Override
    public void setTicketname() {
        ticketname=TrainTicket.class.getSimpleName();
    }
}
package top.huyuxin.builder;
/**
*汽车票
**/
public class BusTicket extends Ticket {


    public BusTicket() {
        super();
    }

    @Override
    public void setTicketname() {
        ticketname=BusTicket.class.getSimpleName();
    }   

}

处理两种票的逻辑应该是一致的。

package top.huyuxin.builder;

public abstract class TicketSeller {

    public abstract void createTicket(); //创建票
    public abstract void checkTicket();  //检查票的生成信息
    public abstract void payTicket();    //支付 
    public abstract void queryTicket();  //查询
    public abstract void drawTicket();   //出票

}

但是细节肯定是不一致的,所以我们创建两个不同的Builder

package top.huyuxin.builder;

public class TrainTicketSeller extends TicketSeller {

    private TrainTicket ticket;

    @Override
    public void createTicket() {
        ticket=new TrainTicket();
        ticket.setTicketname();
    }

    @Override
    public void checkTicket() {
        ticket.isCheck=true;

    }

    @Override
    public void payTicket() {
        ticket.isPayed=true;
    }

    @Override
    public void queryTicket() {
        ticket.isQuery=true;
    }

    @Override
    public void drawTicket() {
        System.out.println(ticket.toString());
    }
}
package top.huyuxin.builder;

public class BusTicketSeller extends TicketSeller {

    private BusTicket busticket;

    @Override
    public void createTicket() {
        busticket=new BusTicket();
        busticket.setTicketname();
    }

    @Override
    public void checkTicket() {
        busticket.isCheck=true;
    }

    @Override
    public void payTicket() {
        busticket.isPayed=true;
    }

    @Override
    public void queryTicket() {
        busticket.isQuery=true;
    }
    @Override
    public void drawTicket() {
        System.out.println(busticket.toString());
    }

}

当在完成票的生成到出票的过程,顺序应该是一定的,不能还没生成票就去支付,还没支付就去查询。所以需要一个指挥者(Director)来控制他们的进程

package top.huyuxin.builder;

public class TicketProgram {

    public static void sellTicket(TicketSeller ticketSeller){
        ticketSeller.createTicket();
        ticketSeller.checkTicket();
        ticketSeller.payTicket();
        ticketSeller.queryTicket();
        ticketSeller.drawTicket();
    }
}

这样我们就可以安心售票了

package top.huyuxin.builder;

public class Main {

    public static void main(String[] args) {
        TrainTicketSeller ticketSeller =new TrainTicketSeller();
        BusTicketSeller busTicketSeller=new BusTicketSeller();

        TicketProgram.sellTicket(ticketSeller);
        TicketProgram.sellTicket(busTicketSeller);
        TicketProgram.sellTicket(ticketSeller);

    }

}

结果:

Ticket [ticketname=TrainTicket, isCheck=true, isPayed=true, isQuery=true]
Ticket [ticketname=TrainTicket, isCheck=true, isPayed=true, isQuery=true]
Ticket [ticketname=BusTicket, isCheck=true, isPayed=true, isQuery=true]

当我们的程序需要买别的票的时候,只需要再次继承抽象类Ticket,并创建处理对应票的Builder就可以了,在TicketProgram 里我们通过依赖注入的方式,使得即使有新的票出售只要逻辑一致,也能正常控制票的出售。
在经典的建造者模式当中Director的控制流程应该是可变的,创建多个不同的sellTicket()方法,通过调动builder的执行顺序产生不同的结果。这就是建造者模式。

填充模式

填充模式,你可能没听过,因为这是我自己起的名字。很多时候对象的构建伴随着很多很多参数的初始化,并且这些参数又不得不先初始化好,大量的setter和getter需要一个管理者来管理一波。比如刚刚的买票,买票可以但是现在的票都是实名制的,在购票前应先获取购票人信息。
于是就有了下面的代码:

package top.huyuxin.builder;

public abstract class Ticket {
    protected String ticketname;
    protected boolean isCheck=false;
    protected boolean isPayed=false;
    protected boolean isQuery=false;

    protected String holdername;
    protected String sex;
    protected int age;
    protected String birthday;
    protected String address;

    public Ticket() {
        super();
    }

    public abstract void  setTicketname();

    public void setCheck(boolean isCheck) {
        this.isCheck = isCheck;
    }

    public void setPayed(boolean isPayed) {
        this.isPayed = isPayed;
    }

    public boolean isQuery() {
        return isQuery;
    }

    public void setQuery(boolean isQuery) {
        this.isQuery = isQuery;
    }

    public String getTicketname() {
        return ticketname;
    }

    public void setTicketname(String ticketname) {
        this.ticketname = ticketname;
    }

    public String getHoldername() {
        return holdername;
    }

    public void setHoldername(String holdername) {
        this.holdername = holdername;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getBirthday() {
        return birthday;
    }

    public void setBirthday(String birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public boolean isCheck() {
        return isCheck;
    }

    public boolean isPayed() {
        return isPayed;
    }

    @Override
    public String toString() {
        return "Ticket [ticketname=" + ticketname + ", isCheck=" + isCheck + ", isPayed=" + isPayed + ", isQuery="
                + isQuery + "]";
    }

}

这使得原来逻辑清晰的Ticket类变得杂乱不堪,由于setter和getter过多可能在初始化的时候你可能漏了用户的sex或则age没有填上。
[设计模式]建造者模式_第1张图片
(翻不完的setter和getter)
于是我们创建一个对象信息的建造者,用来构建对象,在setter的时候我们return this这样使得可以链式调用,

package top.huyuxin.builder;

public class PersonInfo {
    private String holdername;
    private String sex;
    private int age;
    private String birthday;
    private String address;

    public static class Builder{

        private String holdername;
        private String sex;
        private int age;
        private String birthday;
        private String address;

        public Builder setHoldername(String holdername) {
            this.holdername = holdername;
            return this;
        }
        public Builder setSex(String sex) {
            this.sex = sex;
            return this;
        }
        public Builder setAge(int age) {
            this.age = age;
            return this;
        }
        public Builder setBirthday(String birthday) {
            this.birthday = birthday;
            return this;
        }
        public Builder setAddress(String address) {
            this.address = address;
            return this;
        }

        public PersonInfo create(){
            PersonInfo personInfo=new PersonInfo();
            personInfo.holdername=this.holdername;
            personInfo.sex=this.sex;
            personInfo.age=this.age;
            personInfo.birthday=this.birthday;
            personInfo.address=this.address;
         return personInfo;

        }


    }

    @Override
    public String toString() {
        return "PersonInfo [holdername=" + holdername + ", sex=" + sex + ", age=" + age + ", birthday=" + birthday
                + ", address=" + address + "]";
    }
}

在Ticket类初始化的时候便写入的购票人信息

package top.huyuxin.builder;

public abstract class Ticket {
    protected String ticketname;
    protected boolean isCheck=false;
    protected boolean isPayed=false;
    protected boolean isQuery=false;

    protected PersonInfo personInfo;


    public Ticket(PersonInfo personInfo) {
        super();
        this.personInfo=personInfo;
    }


    public abstract void  setTicketname();

    public void setCheck(boolean isCheck) {
        this.isCheck = isCheck;
    }

    public void setPayed(boolean isPayed) {
        this.isPayed = isPayed;
    }

    public boolean isQuery() {
        return isQuery;
    }

    public void setQuery(boolean isQuery) {
        this.isQuery = isQuery;
    }


    @Override
    public String toString() {
        return "Ticket [ticketname=" + ticketname + ", personInfo=" + personInfo.toString() +", isCheck=" + isCheck + ", isPayed=" + isPayed + ", isQuery="
                + isQuery  + "]";
    }
}

在调用的时候也十分的清晰

        PersonInfo xiaoshuangInfo=new PersonInfo.Builder()
                .setHoldername("小双")
                .setSex("women")
                .setAge(18)
                .setBirthday("2000-01-01")
                .setAddress("旮旯")
                .create();
        TicketProgram.sellTicket(ticketSeller,xiaoshuangInfo);
TicketProgram.sellTicket(busTicketSeller,xiaoshuangInfo);

结果:

Ticket [ticketname=BusTicket, personInfo=PersonInfo [holdername=小双, sex=women, age=18, birthday=2000-01-01, address=旮旯], isCheck=true, isPayed=true, isQuery=true]
Ticket [ticketname=TrainTicket, personInfo=PersonInfo [holdername=小双, sex=women, age=18, birthday=2000-01-01, address=旮旯], isCheck=true, isPayed=true, isQuery=true]

通过使用这个填充参数的填充模式使得Ticket对象的构建与表示分离。在填充模式中没有指挥官(Director)但是用于对象的构建还是搓搓有余。

你可能感兴趣的:(设计模式)