封装变动之对象创立
在对象创立的过程中,常常会呈现的一个问题就是通过显示地指定一个类来创建对象,从而导致紧耦合。这是因为创建对象时指定类名将使你受特定实现的束缚而不是特定接口的束缚。这会使将来的变动更加简单。要防止这种状况,就应该间接地创建对象。
这种紧耦合的问题很大水平是由new关键字带来的,因为new的紧耦合呈现,使得紧耦合的类很难独立地被复用,因为它们之间是相互依赖的。并且紧耦合产生单块的零碎,要扭转或者删掉一个类,就必须要了解和扭转其余许多类。这也是导致系统难以保护和移植的一个重要起因。
所以能够通过“对象创立”模式绕开new,从而防止在对象创立(new)过程中所导致的紧耦合(依赖具体的类),以此反对对象创立的稳固。
那么如何防止new呢?举个例子!
public void fun1(){ //... Product p = new Product(); //改为:Product p = productFactory.createProduct(); //... }
这样的形式就是通过一个工厂调用一个办法来创立相应的产品,然而可能大家又会产生一个问题,这样操作尽管解决了Product
的new操作,然而对于ProductFactory
而言不是也须要通过new来产生吗?
对于这个问题,我想是很多人在接触到设计模式的时候都会去思考的问题,既然ProductFactory
还是要用到new,那工厂类还有存在的必要吗?这时,咱们能够会想到两种解决形式,一是将createProdyct()
办法写成静态方法,这样调用的时候天然不须要new了。二是通过注入的形式,比方在利用类当中通过setter或是构造方法传入一个工厂类的对象。
对于静态方法而言,简略地说,即便是应用静态方法,那Product p = ProductFactory.createProduct()
这样仍然是一种紧耦合的形式,因为工厂类无奈替换,和间接new出产品区别不大。
对于注入形式,大家更多的是纳闷,既然能够传入一个工厂类对象,那为什么不间接传入相应的产品,不是更简略间接吗?当然不是的,首先须要明确的是,工厂类的作用是作为一个笼子,这个笼子须要帮忙咱们解放住 ‘将来的变动’ ,要晓得一个产品的变动可能总是大于工厂的变动。在这种状况下,举出一个最简略的例子,你在编码的过程中,可能会用到不只一个产品,那你就可能须要很多setter或者批改构造方法;然而如果这些产品都能够通过这个工厂来获取,是不是就相当于用笼子关住了变动,使其在一个范畴中跳动。
在学习设计模式时,永远要记住的一句话就是“设计模式是用来教会咱们如何应答将来可能的变动”。如果你可能确定本人的零碎将来没有变动,那天然用不到设计模式;或者你的零碎将来全是变动,那也用不到设计模式,设计模式做的就是隔离稳固与变动,如果没有稳固,那就用不到设计模式。
‘new’是一种硬编码,到底 ’硬‘ 在那里,同样一个简略的理由,如果将来构造方法发生变化或者说结构参数减少(缩小),而在源码中有很多中央都是通过new来获取实例对象,找到并批改源码将会是一项很大的工作。
在解决这样的 “对象创立” 问题中就有工厂办法、形象工厂、原型模式和建造者模式等相干设计模式。
工厂办法(Factory Method)
- 用意
定义一个用于创建对象的接口,让子类决定实例化哪一个类。FactoryMethod使得一个类的实例化提早到其子类。
实例
Factory Method绝对于简略工厂而言,齐全遵循了“不改代码”的准则,然而其应用情景相比形象工厂应用条件没有那么高,因而能够说是应用最多的创立型模式之一了。
思考这样一个利用,它能够向用户显示多种文档,比方word、pdf、txt等等。在这个框架中,首先,想到的可能就是利用简略工厂模式。
public interface Document{ public void open(); public void close(); public void save(); // ......}public class PdfDocument implements Document{ @Override public void open(){ //open pdfDocument code System.out.println("open pdf!"); } @Override public void close() { System.out.println("close pdf!"); } @Override public void save() { System.out.println("save pdf!"); } // ......}public class TxtDocument implements Document{ //Txt实现代码,同PdfDocument ......}public class DocumentFactory{ public Document createDocument(String type){ if(type=="pdf"){ return new PdfDocument(); }else if(type=="txt"){ return new TxtDocument(); }else { return null; } }}
//简略工厂模式在客户类当中的调用public class Client { public static void main(String[] args) { DocumentFactory factory = new DocumentFactory(); Document pdfDocument = factory.createDocument("pdf"); pdfDocument.open(); pdfDocument.save(); pdfDocument.close(); Document txtDocument = factory.createDocument("txt"); txtDocument.open(); txtDocument.save(); txtDocument.close(); }}
这样简略工厂模式,在不思考将来新文档类型的状况下,的确是一种不错的实现办法。然而在后续的扩大过程当中,如果须要减少新的文档类,就须要去批改
DocumentFactory
中的createDocument()
办法,减少新的类别,并且客户还必须晓得这些类别能力应用。为了应答这种状况,就呈现了工厂办法。工厂办法就间接将工厂形象进去,每个产品对应一个工厂,打消工厂模式中的条件分支构造(其实还有一种打消条件语句的模式,就是之前“组件合作”当中的策略模式)。
//Document局部不变public interface Document{ public void open(); public void close(); public void save(); ......}public class PdfDocument implements Document{ public void open(){ //open pdfDocument code } // close 和 save ......}public class TxtDocument implements Document{ //Txt实现代码 ......}//并且后续能够扩大新的文档类......
//批改factory局部如下public interface DocumentFactory{ public Document createDocument();}public class PdfDocumentFactory implements DocumentFactory { @Override public Document createDocument() { return new PdfDocument(); }}public class TxtDocumentFactory implements DocumentFactory { @Override public Document createDocument() { return new TxtDocument(); }}//如果后续有新的产品,间接再实现DocumentFactory,失去新的工厂......
//调用过程可做如下批改:public class Client { public static void main(String[] args) { //利用多态性质,间接生成相应的factory子类 //打消了管制耦合 DocumentFactory factory = new PdfDocumentFactory(); Document pdfDocument = factory.createDocument(); pdfDocument.open(); pdfDocument.save(); pdfDocument.close(); factory = new TxtDocumentFactory(); Document txtDocument = factory.createDocument(); txtDocument.open(); txtDocument.save(); txtDocument.close(); }}
有人可能会有疑难,这样不是还没齐全打消new吗?首先这里的客户类曾经到最高的调用档次了,这个过程当中是必然会有new的呈现,不然怎么进行程序调用呢?
咱们所说的打消new的过程是指main与factory之间,产生的一个两头档次(如上面的App)中去打消new。
//这样的代码中,就打消了new的存在//具体的注入过程能够由其余的模式实现,比方Spring中的DIpublic class App{ private DocumentFactory factory; public void setFactory(DocumentFactory factory) { this.factory = factory; } public void operateDoc(){ Document document = factory.createDocument(); document.open(); document.save(); document.close(); }}//main中的代码是最高档次,也是变动最频繁的档次,这里是不可能打消new的public class Client { public static void main(String[] args) { DocumentFactory factory = new PdfDocumentFactory(); App app = new App(); app.setFactory(factory); app.operateDoc(); //同样对于其余的工厂类也是能够采纳同样的形式调用。 ...... }}
这样批改代码的益处在那里呢?第一,不言而喻的就是齐全实现了“开闭准则”的思维,扩大时不再须要去批改源码。第二,有些对象的创立过程可能比较复杂,因而如果间接在应用程序当中应用new或者其余模式创立很麻烦,通过工厂创立之后,就不再须要去关注那些简单的创立过程。第三,通过new创立,始终是一种硬编码的模式,如果在应用程序当中过多的应用这种形式,那么一旦某对象的创立形式产生扭转,批改源码必然是很繁琐的。
- 构造——类创立型模式
参与者
- Product(Document)
定义工厂办法中工厂创立的对象的接口。
- ConcreteProduct(PdfDocument、TxtDocument)
实现Product的接口。
- Creator(DocumentFactory)
申明工厂办法——createProduct(),能够调用该办法返回一个Product类型的对象。
- ConcreteCreator(PdfDocumentFactory、TxtDocumentFactory)
重定义工厂办法以返回具体的ConcreteProduct。
- Client(客户类)
应用工厂和产品,工厂办法模式中,客户类也是一个重要的参与者,因为工厂办法次要的作用就是分来到客户类与产品类之间的耦合关系,所以脱离客户类去谈工厂办法模式时,总会感觉差了些什么货色,无奈齐全领会到工厂办法模式的劣势。
- Product(Document)
适用性
在下列状况下能够应用Factory Method模式:
- 当一个类不晓得它所必须创立的对象的类的时候。
- 当一个类心愿由它的子类来指定它所创立的对象的时候。
- 当类将创建对象的职责委托给多个帮忙子类中的某一个,并且你心愿将哪一个帮忙子类是代理者这一信息部分化的时候。
简略地说,就是应用过程中只须要申明一个形象工厂类的援用,具体调用那个工厂去生成那个对象,是由调用者去确定的。
- 相干模式
Abstract Factory常常用工厂办法来实现,形象工厂创立产品的过程就能够应用工厂办法来实现。
工厂办法通常在Template Method中被调用,这一点在“组件合作”当中也提到过。
思考
- Creator的两种实现状况。第一种状况,Creator只作为形象层,也就是只申明接口,不做任何的实现;这种状况就必须要子类来实现。第二种状况,Creator作为一个具体的实现类,而不是抽象类,这种状况下,Creator能够提供一个缺省的实现接口,这样即便没有子类重写它,客户能够通过这样一个缺省的实现实现工作。
- 灵活运用工厂办法模式。作为一种创立类模式,在任何须要生成简单对象的中央,都能够应用工厂办法模式。有一点须要留神的中央就是简单对象适宜应用工厂办法模式,而简略对象,特地是只须要通过 new 就能够实现创立的对象(这也是为什么工厂办法解说用到的例子总是无奈压服人的起因之一),无需应用工厂办法模式;因为应用工厂办法模式,就须要引入一个工厂类,会减少零碎的复杂度。
形象工厂(Abstract Factory)
- 用意
提供一个创立一系列相干或相互依赖对象的接口,而无需指定他们具体的类。
实例
假设存在这样一个服务层,该层当中须要做的就是拜访数据库中的数据,并且执行一系列的相干操作。依据面向接口编程的思维,能够先作这样一个代码编写。
//对数据库进行拜访的三个接口//先建设连贯,再执行相干操作,最初返回相应后果public interface DBConnection{}public interface DBCommand{}public interface DBDataReader{}//对于MySql,能够建设以下实现public class MySqlDBConnection implements DBConnection{}public class MySqlDBCommand implements DBCommand{}public class MySqlDBDataReader implements DBDataReader{}//同样对于Sql Server,Oricle也是这样的实现......
这样的实现下,咱们能够说是满足了面向接口编程的一个思维;并且在实现中,咱们能够为每个接口,依照工厂办法模式,为其创立一个工厂。
//工厂接口public interface DBConnectionFactory{ public DBConnection createDBConnetion();}public interface DBCommandFactory{ public DBCommand createDBCommand();}public interface DBDataReaderFactory{ public DBDataReader createDBDataReader();}//而后对于每个具体的数据库,实现不同的具体工厂//以MySql为例public class MySqlDBConnetionFactory implements DBConnectionFactory { @Override public DBConnection createDBConnetion() { return new MySqlDBConnection(); }}public class MySqlDBCommandFactory implements DBCommandFactory { @Override public DBDBCommand createDBCommand() { return new MySqlDBCommand(); }}public class MySqlDataReaderFactory implements DataReaderFactory { @Override public DBDataReader createDataReader() { return new MySqlDataReader(); }}//剩下的Orcle,Sql Server也是如此......
工厂模式办法的调用就不再演示,区别和工厂办法中的
Document
例子中差异不大。对于这样的实现,尽管咱们很好的利用了工厂办法模式,然而也引入了工厂办法模式的一个弊病——大量的对象和类(本例当中,三个系列,每个系列三个产品,光产品就是9个子类;每个产品再对应一个工厂,一共就是18个子类)。在应用的过程中,反而可能显著的感觉到零碎复杂度不减反增。并且,
DBConnection
、DBCommand
和DBDataReader
显著是有着肯定的关系的,换句话说,MySql建设的DBConnection
是和MySqlDBCommand、MySqlDBDataReader
一起应用的,如果呈现MySqlDBConnection、OricleDBCommand、SqlServerDBDataReader
这种组合必定是无奈失常执行的。这时形象工厂的呈现,就很好的解决了这样的问题。//首先,具体的产品类不会发生变化,简化的次要是工厂档次//先形象出形象工厂,将产品系列的创立办法合并到一个接口中public interface DBFactory{ public DBConnection createDBConnetion(); public DBCommand createDBCommand(); public DBDataReader createDBDataReader();}//依据不同的具体工厂,创立具体的对象public class MySqlDBFactory implements DBFactory { @Override public DBConnection createDBConnetion() { return new MySqlDBConnection(); } @Override public DBCommand createDBCommand() { return new MySqlDBCommand(); } @Override public DBDataReader createDBDataReader() { return new MySqlDBDataReader(); }}//Oricle,sql server的工厂,同样如此......
形象工厂次要是对工厂档次的简化,这样批改下来,比照工厂办法模式,缩小了2/3的工厂子类创立,只须要3个工厂(有多少个产品系列就有多少个工厂子类)就能够实现产品的创立。
这样的一种创立工厂形式,不仅缩小了工厂的数量,而且使得产品的一致性得以保障,它能够保障,一次只能应用同一个系列当中的对象。
public class Client { public static void main(String[] args) { DBFactory factory = new MySqlDBFactory(); App app = new App(); app.setFactory(factory); app.operate(); //同样对于其余的工厂类也是能够采纳同样的形式调用。 // ...... }}class App{ private DBFactory factory; public void setFactory(DBFactory factory) { this.factory = factory; } public void operate(){ DBConnection connection = factory.createDBConnetion(); DBCommand command = factory.createDBCommand(); DBDataReader reader = factory.createDBDataReader(); //执行相干操作 ..... }}
这样的利用程序代码,在肯定水平上就缩小了工厂子类的数量,并且在
operate()
中保障了产品系列的一致性,使得MysqlDBFactory
生成的产品,只会是与MySql相干的。- 构造——对象创立型模式
参与者
- AbstractFactory(DBFactory)
申明一个创立形象产品对象的操作接口。
- ConcreteFactory(MySqlDBFactory)
实现创立具体产品对象的操作。
- AbstractProduct(DBConnection、DBCommand、DBDataReader)
为一类产品对象申明一个接口。
- ConcreteProduct(MySqlDBConection、MySqlDBCommand、MySqlDBDataReader)
定义一个将被相应的具体工厂创立的产品对象,并实现形象产品的相应接口。
- Client
调用形象工厂和形象产品提供的接口。在创建者模式当中,客户类也是重要的参加成员,因为对创立模式的了解容易凌乱的点正是在客户类中的调用过程 (new) 产生的,对于这个问题,曾经在后面做过很多解释了,不再多说。
- AbstractFactory(DBFactory)
适用性
以下状况能够应用AbstractFactory模式:
- 一个零碎要独立于它的产品的创立、组合和示意时。
- 一个零碎要由多个产品系列中的一个来配置时。
- 当你要强调一系列相干的产品对象的设计以便进行联结应用时。
- 当你提供一个产品类库,而只想显示它们的接口而非实现时。
- 相干模式
Singleton:一个具体的工厂通常会是一个单件。因为在一个利用中,个别每个产品系列只须要一个具体工厂。
Factory Method:在Abstract Factory中,仅仅是申明一个创建对象的接口,真正的创立过程是由具体工厂实现的。这时,能够为每一个办法对应的具体对象之间再定义一个工厂办法。但其问题就在于,这样的做法就像是在工厂办法上再套上一层形象工厂,从而又减少了零碎的复杂度。
思考
- 难以反对新品种的产品 对于工厂模式而言,它的最大长处就在于保障了产品的一致性,但也正是如此,这就使得它的产品系列须要保持稳定,如果在后续的过程中呈现新的产品,比方在实例当中须要减少一个新的性能系列,就须要去扩大
DBFactory
接口,并且波及到DBFactory
及其子类的扭转。 - 定义可扩大的工厂 这是对于新品种产品创立灵活性的进步,然而不太平安;就是给创立 对象的操作减少一个参数,该参数来指定将被创立的对象品种。应用这种形式,形象工厂就只须要一个“Create”办法和一个标识符参数即可实现创立操作。但问题就在于,客户须要齐全理解所有的参数能力更好应用工厂创立本人所须要的对象。
- 难以反对新品种的产品 对于工厂模式而言,它的最大长处就在于保障了产品的一致性,但也正是如此,这就使得它的产品系列须要保持稳定,如果在后续的过程中呈现新的产品,比方在实例当中须要减少一个新的性能系列,就须要去扩大
原型模式(Prototype)
- 用意
用原型实例指定对象的创立品种,并且通过拷贝这些原型创立新的对象。
实例
Prototype模式,有点像是对工厂办法模式中产品与工厂的合并。怎么说呢?看上面的代码:
//工厂办法模式中的产品类与工厂办法类public interface Document{ public void open(); public void close(); public void save(); ......}public interface DocumentFactory{ public Document createDocument();}
这是在Factory Method中应用的创立形式,而原型做的事就是,不再用工厂来进行创立,而是转而克隆的形式。变成上面这样:
//合并Document和DocumentFactorypublic abstract class Document implements Cloneable{ public void open(); public void close(); public void save(); ...... //相当于Factory中的createDocument(); public Object clone() { Object clone = null; try { clone = super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return clone; }}public class PdfDocument implements Document{ @Override public void open(){ //open pdfDocument code System.out.println("open pdf!"); } @Override public void close() { System.out.println("close pdf!"); } @Override public void save() { System.out.println("save pdf!"); } //......}//文档类的实现与工厂办法中的一样......
那么在具体的客户类当中就是通过这样一种形式来进行调用:
public class App{ //在工厂办法模式当中,这里是documentFactory private Document prototype; public void setDoucument(Document document){ prototype = document; } public void useDocument(){ //documentFactory.createDocument(); Document doc = prototype.clone(); //而后应用prototype克隆进去的doc进行操作 doc.open(); ...... }}//在客户类中调用体现public class Client { public static void main(String[] args) { Document doc = new PdfDocument(); App app = new App(); app.setFactory(doc); app.useDocument(); //同样对于其余的工厂类也是能够采纳同样的形式调用。 //...... }}
问题来了,为什么不间接用原型(prototype),而是要多一步克隆?解决这个问题,首先要明确的是,咱们应用原型的目标不是将原型作为客户类的一个属性去应用,而是一个创建者。既然是一个创建者,那么在应用的过程中,就不只一个中央会用到同样类型的对象;如果在不同的中央都间接应用原型,可能会在某个中央批改了原型的值,从而使得其余间接应用原型的办法呈现不可预知的谬误。
- 构造——对象创立型模式
参与者
- Prototype(Document)
申明一个克隆本身的接口。
- ConcretePrototype(PdfDocument...)
继承Prototype并实现克隆本身的接口。
- Client
让一个原型克隆本身从而创立一个新的对象。
- Prototype(Document)
适用性
- 当一个零碎应该独立于它的产品创立、形成和示意时,能够应用Prototype模式。
- 当要实例化的类是在运行时候指定时,比方动静装载。
- 为了防止创立一个产品类平行的工厂类档次时。
- 当一个类的实例只能有几种不同状态组合中的一种时,建设相应数目的原型并克隆他们能够比每次用适合的状态手工实例化该类更不便一些。
- 相干模式
Abstract Factory和Prototype在某种方面是相互竞争的,然而在某种状况下也是能够一起应用,比方,在形象工厂中存储一个被克隆的产品汇合,在应用时,间接依据汇合中的对象返回相应的产品。
大量应用Composite(组合模式)和Decorator(装璜器模式)的设计上也能够采纳Protorype来缩小Composite或Decorator对象的创立。
思考
- 缩小了子类的结构。实例当中就能够看出,原型模式简化了工厂办法模式中的工厂类,因而,缩小了许多子类的创立。
- 资源优化。类初始化可能须要消化十分多的资源,这个资源包含数据、硬件资源等等,应用原型模式就能够缩小这样一个初始化过程。
- 深、浅拷贝的问题。对于java而言,浅拷贝实现 Cloneable,深拷贝是通过实现 Serializable 读取二进制流。
建造者模式( Builder)
- 用意
将一个简单对象的构建与它的示意拆散,使得同样的构建过程能够有不同的示意。
实例
在游戏场景当中,尤其是3d场景中,必不可少就是建筑物,比如说房子。对房子的构建必定不是一下全部构建实现的,而是会分成几个局部,比方墙、窗户、地板、房顶、门,一部分、一部分地去构建。
public abstract class House{ //房子属性,纹理、材质... private Texture texture; private Material material; ...... //墙、窗户、地板、房顶、门 public Wall buildWall(); public Window buildWindow(); public Floor buildFloor(); public Door buildDoor(); public Roof buildRoof(); //房子构建过程 public void buildHouse(){ buildFloor(); Wall[] walls = new Wall[4]; for(int i=0;i<walls.length;i++) walls[i] = buildWall(); Window window = buildWindow(); wall[1].setWindow(window); Door door = builDoor(); wall[2].setDoor(door); buildRoof(); }}
这种构建形式,采纳的显著就是模板办法(Template Method),这种实现形式还能够依据不同的房子类型,实现具体的细节。
//石头屋public class StoneHouse extends House{ //具体实现细节 .......}//茅草屋public class ThatchedHouse extends House{ //具体实现细节 .......}
//依照模板主办法在客户类中的调用模式体现:public class Client{ public static void main(String[] args){ //只须要生成一个相应对象即可在游戏场景中实现相应类型房子的创立 House house = new StoneHouse(); house.buildHouse(); //生成石头屋 house = new ThatchedHouse(); house.buildHouse(); //生成茅草屋 }}
这种实现有什么问题呢?类太臃肿了,对吧~这样的实现过程,能够体现复用的思维,然而问题之一就在于所有的内容全副都放在了一个类中,体现不出繁多职责和类的信息与行为集中;这时就能够将创立过程分离出来,造成一个Builder,由这样一个Builder来专门负责创立。
//Directorpublic class House{ //房子属性,纹理、材质... private Texture texture; private Material material; ...... //减少builder的引入 private HouseBuilder houseBuilder; public void setHouseBuilder(HouseBuilder hBuilder){ houseBuilder = hbuilder; } //房子构建过程 public void buildHouse(){ houseBuilder.buildFloor(); Wall[] walls = new Wall[4]; for(int i=0;i<walls.length;i++) walls[i] = houseBuilder.buildWall(); Window window = houseBuilder.buildWindow(); wall[1].setWindow(window); Door door = houseBuilder.builDoor(); wall[2].setDoor(door); houseBuilder.buildRoof(); }}//分离出来的builderpublic interface HouseBuilder{ //墙、窗户、地板、房顶、门 public Wall buildWall(); public Window buildWindow(); public Floor buildFloor(); public Door buildDoor(); public Roof buildRoof();}public class StoneHouseBuilder implements HouseBuilder{ //具体实现细节 .......}public class ThatchedHouseBuilder implements HouseBuilder{ //具体实现细节 .......}
//批改过后,在客户类中的调用模式体现:public class Client{ public static void main(String[] args){ //只须要生成一个相应对象即可在游戏场景中实现相应类型房子的创立 House house = new House(); HouseBuilder builder = new StoneHouseBuilder(); house.setHouseBuilder(builder); house.buildHouse(); builder = new ThatchedHouseBuilder(); //这个set过程能够运行时实现 house.setHouseBuilder(builder); house.buildHouse(); }}
通过这样一种形式,实现简单对象构建与示意的拆散,并且,对于不同的房子对象,如果房子其余参数没有任何差异,就只须要传入相应的builder即可,而不须要再生成各种各样的子类(如
StoneHouse、ThatchedHouse
)。一旦生成对象,只须要批改其builder就能够马上扭转其对象示意,而不须要新生成对象。并且这种批改过程,是能够动静实现的,就如果Spring当中的依赖注入过程一样,能够在运行时刻实现,而不肯定是一开始就确定的
- 构造——对象创立型模式
参与者
- Builder(HouseBuilder)
为创立一个Product对象的各个部件指定形象接口。
ConcreteBuilder(StoneHouseBuilder、ThatchedHouseBuilder)
- 实现Builder的接口以结构各拆卸该产品的各个部件。
- 定义并明确它所创立的示意。
- Director(House)
结构一个应用builder的对象。
- Product(Wall、Window...)
蕴含了定义组成部件的类以及被结构的简单对象等。
- Builder(HouseBuilder)
适用性
Builder的实用状况:
- 当创立简单对象的算法应该独立于该对象的组成部分,以及它们的拆卸形式时。
- 当结构过程必须容许被结构的对象的不同的示意时。
Builder模式更多的是体现的一种思维,而不是具体的过程,这种思维就是,当一个类的信息与行为过于臃肿时,兴许能够采纳Builder这种形式对类的信息与行为进行从新划分,从而使得类看起来更加的“轻” 。
- 相干模式
Abstract Factory和Builder都是对简单对象的创立封装,但二者的区别在于,Builder着重于一步一步构建一个简单对象,而Abstract Factory着重于多个系列产品对象的创立,并且系列对象之间有着某种分割。
Composite模式中对象通常状况下就是用Builder生成的。
思考
- 能够扭转产品的外部示意 Builder对象提供给Director一个结构产品对象的外部接口,从而使得产品的示意和内部结构得以暗藏。因而,在构建过程中,只须要替换不同的Builder就能够失去不同的示意。
- Builder中的办法能够缺省为空 这样在具体的实现过程中,客户能够只实现他们感兴趣的操作,这种形式其实在很多模式中都能够利用,其最次要的思维就是能用默认配置当然是最好的。
最初,最近很多小伙伴找我要Linux学习路线图,于是我依据本人的教训,利用业余时间熬夜肝了一个月,整顿了一份电子书。无论你是面试还是自我晋升,置信都会对你有帮忙!
收费送给大家,只求大家金指给我点个赞!
电子书 | Linux开发学习路线图
也心愿有小伙伴能退出我,把这份电子书做得更完满!
有播种?心愿老铁们来个三连击,给更多的人看到这篇文章
举荐浏览:
- 干货 | 程序员进阶架构师必备资源免费送
- 神器 | 反对搜寻的资源网站