版权声明:转载必须注明本文转自晓_晨的博客:http://blog.csdn.net/niunai112
目录
导航
设计模式之六大设计原则
设计模式(一)单例模式
设计模式(二)工厂模式
设计模式(三)策略模式
设计模式(四)适配器模式
设计模式(五)享元模式
设计模式(六)建造者模式
设计模式(七)原型模式
设计模式(八)桥接模式
设计模式(九)外观模式
设计模式(十)组合模式
设计模式(十一)装饰器模式
设计模式(十二)代理模式
设计模式(十三)迭代器模式
设计模式(十四)观察者模式
设计模式(十五)中介者模式
设计模式(十六)命令模式
设计模式(十七)状态模式
设计模式(十八)访问者模式
设计模式(十九)责任链模式
设计模式(二十)解释器模式
设计模式(二十一)备忘录模式
设计模式(二十二)模板模式
设计模式总结篇(为什么要学习设计模式,学习设计模式的好处)
前言
在开发过程,有的时候会出现一个复杂对象的创建工作,这个对象一般组装模式固定,但是其中的参数会变,比如像电脑,汽车等,可拆分的东西,基本都能使用这个模式,只是看有没有必要,一些本来就是固定死的东西,用工厂模式或者享元模式会更好。
例子
假如你是一家云提供商,你的客户需要不同种类的产品,你要给不同客户提供产品。
/***
*
*@Author ChenjunWang
*@Description:产品类,服务器有操作系统,所用语言,所选服务器和所选数据库
*@Date: Created in 21:05 2018/3/20
*@Modified By:
*
*/
public class ServerProduct {
String os;
String language;
String server;
String database;
public String getOs() {
return os;
}
public void setOs(String os) {
this.os = os;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public String getDatabase() {
return database;
}
public void setDatabase(String database) {
this.database = database;
}
public String getEnvironment() {
return "ServerProduct{" +
"os='" + os + '\'' +
", language='" + language + '\'' +
", server='" + server + '\'' +
", database='" + database + '\'' +
'}';
}
}
假设有个客户选了经典套餐
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 21:19 2018/3/20
*@Modified By:
*
*/
public class Customer {
public static void main(String[] args) {
ServerProduct customer = new ServerProduct();
customer.setOs("Ubuntu");
customer.setLanguage("Java");;
customer.setDatabase("Mysql");
customer.setServer("Tomcat");
System.out.println("客户1要的环境:" + customer.getEnvironment());
}
}
运行结果如下
-------------------------------
客户1要的环境:ServerProduct{os='Ubuntu', language='Java', server='Tomcat', database='Mysql'}
没问题,环境出来了,客户很满意,后来又有一个客户说系统要centos,然后我们又要把全部流程走一遍
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 21:19 2018/3/20
*@Modified By:
*
*/
public class Customer {
public static void main(String[] args) {
ServerProduct customer = new ServerProduct();
customer.setOs("Ubuntu");
customer.setLanguage("Java");;
customer.setDatabase("Mysql");
customer.setServer("Tomcat");
System.out.println("客户1要的环境:" + customer.getEnvironment());
ServerProduct customer2 = new ServerProduct();
customer2.setOs("Ubuntu");
customer2.setLanguage("Java");;
customer2.setDatabase("Mysql");
customer2.setServer("Tomcat");
System.out.println("客户2要的环境:" + customer2.getEnvironment());
}
}
运行结果如下
-------------------------------
客户1要的环境:ServerProduct{os='Ubuntu', language='Java', server='Tomcat', database='Mysql'}
客户2要的环境:ServerProduct{os='CentOS', language='Java', server='Tomcat', database='Mysql'}
这样每次创建一个环境都需要写大量的重复代码,所以LZ
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 21:12 2018/3/20
*@Modified By:
*
*/
public interface Builder {
Builder installOS(String OS);
Builder installLanguage(String language);
Builder installServer(String server);
Builder installDatabase(String database);
ServerProduct getProduct();
}
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 22:04 2018/3/20
*@Modified By:
*
*/
public class Classic implements Builder{
private ServerProduct serverProduct = new ServerProduct();
@Override
public Builder installOS(String OS) {
serverProduct.os = OS;
return this;
}
@Override
public Builder installLanguage(String language) {
serverProduct.language = language;
return this;
}
@Override
public Builder installServer(String server) {
serverProduct.server = server;
return this;
}
@Override
public Builder installDatabase(String database) {
serverProduct.database = database;
return this;
}
@Override
public ServerProduct getProduct() {
return serverProduct;
}
}
/***
*
*@Author ChenjunWang
*@Description:
*@Date: Created in 22:11 2018/3/20
*@Modified By:
*
*/
public class Director {
private Builder builder = new Classic();
public ServerProduct createClassicUbuntuEnvironment(){
builder.installOS("Ubuntu").installLanguage("Java").installServer("Tomcat").installDatabase("Mysql");
return builder.getProduct();
}
public ServerProduct createClassicCentOSEnvironment(){
builder.installOS("CentOS").installLanguage("Java").installServer("Tomcat").installDatabase("Mysql");
return builder.getProduct();
}
}
public class Customer {
public static void main(String[] args) {
Director director = new Director();
ServerProduct classicCentOSEnvironment1 = director.createClassicCentOSEnvironment();
System.out.println("创建第一个环境:" + classicCentOSEnvironment1.getEnvironment());
ServerProduct classicCentOSEnvironment2 = director.createClassicUbuntuEnvironment();
System.out.println("创建第二个环境:" + classicCentOSEnvironment2.getEnvironment());
}
}
运行结果如下
--------------------------
创建第一个环境:ServerProduct{os='CentOS', language='Java', server='Tomcat', database='Mysql'}
创建第二个环境:ServerProduct{os='Ubuntu', language='Java', server='Tomcat', database='Mysql'}
UML图
其实,建造者模式到这就结束了,但是LZ还是要拓展一下,这里存在一个大问题,就是假如使用上面的方法的话,director 再次调用create方法的话,之前的信息就会被替换掉,因为他们引用的是同一个对象。所以Main应该要按下面这样写才对。
public class Customer {
public static void main(String[] args) {
Director director = new Director();
ServerProduct classicCentOSEnvironment1 = director.createClassicCentOSEnvironment();
System.out.println("创建第一个环境:" + classicCentOSEnvironment1.getEnvironment());
director = new Director();
classicCentOSEnvironment2 = director.createClassicUbuntuEnvironment();
System.out.println("创建第二个环境:" + classicCentOSEnvironment2.getEnvironment());
System.out.println("创建第一个环境:" + classicCentOSEnvironment1.getEnvironment());
}
}
---------------------------------------------------
创建第一个环境:ServerProduct{os='CentOS', language='Java', server='Tomcat', database='Mysql'}
创建第二个环境:ServerProduct{os='Ubuntu', language='Java', server='Tomcat', database='Mysql'}
创建第一个环境:ServerProduct{os='CentOS', language='Java', server='Tomcat', database='Mysql'}
这样就没有什么问题了。每次新建出来的环境都是不同的对象。
总结
优点
建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。由于指挥者类针对抽象建造者编程,增加新的具体建造者无须修改原有类库的代码,系统扩展方便,符合“开闭原则”。
可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰。
缺点
建造者模式所创建的产品具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,不适合使用建造者模式,因此其使用范围受到一定的限制。
如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大,增加系统的理解难度和运行成本。
Git地址
本篇实例Github地址:https://github.com/stackisok/Design-Pattern/tree/master/src/builder
有什么不懂或者不对的地方,欢迎留言。
喜欢LZ文章的小伙伴们,可以关注一波,也可以留言,LZ会回你们的。
觉得写得不错的小伙伴,欢迎转载,但请附上原文地址,谢谢^_^!