Java 创建型模式
持续更新…
创建者模式的主要关注点是‘怎样创建对象?’,它的主要特点是‘将对象的创建和使用分离’。
这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。
创建型模式分为:
- 单例模式
- 工厂方法模式
- 抽象工厂模式
- 原型模式
- 建造者模式
单例模式
单例模式是Java中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种出创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类对象。
单例模式的结构
单例模式主要有以下角色:
- 单例类,只能创建一个实例的类
- 访问类,使用单例的类
工厂模式
工厂模式是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。主要用于解决接口问题。
UML类图实例:
代码实现如下:
package com.wu;
public abstract class NoteBook {
public abstract void writeContent(String content);
}
package com.wu;
public class EnglishBook extends NoteBook{
private static final String TYPE = "英语本";
private String content;
public void writeContent(String content){
this.content = content;
}
public String getContent(){
return "内容为:" + content;
}
public String getDescription(){
return "这是一个英语本";
}
}
package com.wu;
public class MathBook extends NoteBook{
private static final String TYPE = "数学本";
private String content;
public void writeContent(String content){
this.content = content;
}
public String getContent(){
return "内容为:" + content;
}
public String getDescription(){
return "这是一个数学本";
}
}
package com.wu;
public class BookStore {
public NoteBook sellBook(String type) throws RuntimeException{
NoteBook book = null;
if(type.equals("英语本")){
book = new EnglishBook();
}else if(type.equals("数学本")){
book = new MathBook();
}else{
throw new RuntimeException();
}
return book;
}
}
package com.wu;
public class Client {
public static void main(String[] args) {
// 创建书店对象
BookStore booKStore = new BookStore();
// 销售数学本
NoteBook book = booKStore.sellBook("数学本");
System.out.println(((MathBook) book).getDescription());
// 销售英语本
book = booKStore.sellBook("英语本");
System.out.println(((MathBook) book).getDescription());
}
}
可以分析以上的代码,由于通过BookStore来创建(new)Book对象,所以导致了BookStore对Book对象的耦合,假如我们需要更换对象的时候,就会修改相应的代码,这显然违背了软件设计的开闭原则。如果我们使用工厂来生产对象,我们就只需要和工厂来进行信息交换就可以了,就可以彻底和对象解耦,因此,工厂模式的最大优势就是:解耦合
三种工厂模式
- 简单工厂模式(不属于经典设计模式)
- 工厂方法模式
- 抽象工厂模式
简单工厂模式
简单工厂角色
- 抽象产品:定义了产品规范
- 具体产品:实现或者继承抽象产品的子类
- 具体工厂:提供了创建产品的方法,调用者通过该方法来获取产品
优缺点
- 优点:
封装了创建对象的过程,可以通过参数直接获取对象。把对象的创建和业务逻辑层分开,这样以后就可以避免了修改客户代码,如果要实现新的产品就可以直接修改工厂类,而不需要原代码中修改,这样就降低了客户代码修改的可能性,更加容易扩展。- 缺点:
增加新的产品还是需要修改工厂类的代码,违背了“开闭原则”
UML类图:
修改的代码:
package com.wu;
public class SimpleBookFactory {
public NoteBook createBook(String type){
NoteBook noteBook = null;
if(type.equals("英语本")){
noteBook = new EnglishNoteBook();
}else if(type.equals("数学本")){
noteBook = new MathNoteBook();
}else{
throw new RuntimeException();
}
return noteBook;
}
}
package com.wu;
public class BookStore {
public NoteBook sellBook(String type) throws RuntimeException{
SimpleBookFactory factory = new SimpleBookFactory();
NoteBook noteBook = factory.createBook(type);
return noteBook;
}
}
静态工厂:
package com.wu;
public class SimpleBookFactory {
public static NoteBook createBook(String type){
NoteBook noteBook = null;
if(type.equals("英语本")){
noteBook = new EnglishNoteBook();
}else if(type.equals("数学本")){
noteBook = new MathNoteBook();
}else{
throw new RuntimeException();
}
return noteBook;
}
}
工厂方法模式
针对上面中的未遵循开闭原则,我们可以通过工厂方法模式来完美地解决。
概念
定义一个用于创建对象的接口,让子类决定实例化哪个产品类对象。工厂方法
工厂方法模式角色
- 抽象工厂:提供了创建产品的接口,调用者通过它访问具体的工厂的工厂方法来创建产品。
- 具体工厂:主要是实现抽象工厂中的抽象方法,完成具体产品的创建。
- 抽象产品:定义了产品规范,描述了产品的主要特性和功能。
- 具体产品:实现了抽象产品角色所定义的接口,有具体工厂来创建,它同具体工厂之间一一对应。
优缺点
- 优点:
用户只需要知道具体工厂的名称就可以得到所要的产品,无须知道产品的具体创建过程
在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则- 缺点:
每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度
UML类图:
代码实现:
package com.wu;
public class BookStore {
private BookFactory factory;
public void setFactory(BookFactory factory) {
this.factory = factory;
}
public NoteBook sellBook() throws RuntimeException{
NoteBook book = factory.createBook();
return book;
}
}
package com.wu;
public abstract class NoteBook {
public abstract void writeContent(String content);
}
package com.wu;
public interface BookFactory {
public NoteBook createBook();
}
package com.wu;
public class MathBookFactory implements BookFactory{
@Override
public NoteBook createBook() {
return new MathNoteBook();
}
}
package com.wu;
public class EnglishBookFactory implements BookFactory{
@Override
public NoteBook createBook() {
return new EnglishNoteBook();
}
}
package com.wu;
public class MathNoteBook extends NoteBook {
private static final String TYPE = "数学本";
private String content;
public void writeContent(String content){
this.content = content;
}
public String getContent(){
return "内容为:" + content;
}
public String getDescription(){
return "这是一个数学本";
}
}
package com.wu;
public class EnglishNoteBook extends NoteBook {
private static final String TYPE = "英语本";
private String content;
public void writeContent(String content){
this.content = content;
}
public String getContent(){
return "内容为:" + content;
}
public String getDescription(){
return "这是一个英语本";
}
}
package com.wu;
public class Client {
public static void main(String[] args) {
// 创建书店对象
BookStore bookStore = new BookStore();
// 销售数学本
MathBookFactory mathBookFactory = new MathBookFactory();
bookStore.setFactory(mathBookFactory);
NoteBook noteBook = bookStore.sellBook();
System.out.println(((MathNoteBook) noteBook).getDescription());
// 销售英语本
EnglishBookFactory englishBookFactory = new EnglishBookFactory();
bookStore.setFactory(englishBookFactory);
noteBook = bookStore.sellBook();
System.out.println(((EnglishNoteBook) noteBook).getDescription());
}
}
抽象工厂模式
抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
概念
是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式时工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
抽象工厂模式主要角色
- 抽象工厂:提供了创建产品的接口,它包含多个创建产品的方法,可以创建多个不同等级的产品
- 具体工厂:主要是实现抽象工厂中的多个抽象方法,完成具体产品的创建
- 抽象产品:定义了产品的规范,描述了产品的主要特性和功能,抽象工厂模式有多个抽象产品
- 具体产品:实现了抽象产品角色所定义的接口,由具体工厂来创建,它同具体工厂之间是多对一的关系
优缺点
- 优点:
当一个产品族中的多个对象设计成一起工作时,它能保证客户端始终使用一个产品族中的对象- 缺点:
当产品族中需要增加一个新产品时,所有工厂类都需要进行修改
使用场景
- 当需要创建的对象是一系列相互依赖的产品族时
- 系统中有多个产品族,但每次只使用其中的某一族产品
- 系统中提供了产品的类库j,且所有产品的接口相同,客户端不依赖产品实例的创建细节和内部结构
UML类图:
代码如下:
package com.wu;
public interface BookFactory {
// 生产本子的功能
NoteBook createNoteBook();
// 生产教科书的功能
TextBook createTextBook();
}
package com.wu;
public class Client {
public static void main(String[] args) {
MathBookFactory mathBookFactory = new MathBookFactory();
// 创建数学教科书
TextBook mathTextBook = mathBookFactory.createTextBook();
mathTextBook.description();
// 创建数学本子
NoteBook mathNoteBook = mathBookFactory.createNoteBook();
mathNoteBook.description();
EnglishBookFactory englishBookFactory = new EnglishBookFactory();
// 创建英语本子
NoteBook englishNoteBook = englishBookFactory.createNoteBook();
englishNoteBook.description();
// 创建英语教科书
TextBook englishTextBook = englishBookFactory.createTextBook();
englishTextBook.description();
}
}
package com.wu;
public class EnglishBookFactory implements BookFactory{
@Override
public NoteBook createNoteBook() {
return new EnglishNoteBook();
}
@Override
public TextBook createTextBook() {
return new EnglishTextBook();
}
}
package com.wu;
public class EnglishNoteBook extends NoteBook {
@Override
public void description(){
System.out.println("这是一个英语本… ");
}
}
package com.wu;
public class EnglishTextBook extends TextBook{
@Override
public void description() {
System.out.println("这是一本英语教科书… ");
}
}
package com.wu;
public class MathBookFactory implements BookFactory{
@Override
public NoteBook createNoteBook() {
return new MathNoteBook();
}
@Override
public TextBook createTextBook() {
return new MathTextBook();
}
}
package com.wu;
public class MathNoteBook extends NoteBook {
@Override
public void description(){
System.out.println("这是一个数学本… ");
}
}
package com.wu;
public class MathTextBook extends TextBook{
@Override
public void description() {
System.out.println("这是一本数学教科书… ");
}
}
package com.wu;
public abstract class NoteBook {
public abstract void description();
}
package com.wu;
public abstract class TextBook {
public abstract void description();
}