本文目录:

LCODER设计模式一:创建型模式

规划形式分为创立型形式、结构型形式和行为形式。
创立型形式: 提供了创立目标的机制。是这一篇博客即将介绍的内容。
结构型形式: 介绍如何将目标和类拼装成较大的结构,并一起坚持结构的灵活和高效。
行为形式: 担任目标间的高效交流和责任委派。

为什么要学习规划形式呢?
由于规划形式是针对软件规划中常见问题的工具箱,其间的工具便是各种警告实践验证的解决方案。熟悉了规划形式,会让你的代码愈加的健壮。

面向目标的六大准则

单一责任准则 : (Single Responsibility Principle SRP) 就一个类而言,应该仅有一个引起它改变的原因。
开闭准则 :(Open Close Principle OCP)软件中的目标(类、模块、函数等)应该关于扩展是敞开的,可是,关于修正是封闭的。
里式替换准则 :(Liskov Substitution Principle LSP)子类能够扩展父类的功用,但不能改变父类的功用。
依靠倒置准则:(Dependence Inversion Principle DIP)面向接口编程。模块间的依靠经过笼统发送,完成类之间不发生直接的依靠关系,其依靠关系是经过接口或笼统类发生的。
接口阻隔准则:(InterfaceSegregation Principles ISP)类间的依靠关系应该建立在最小的接口上。
迪米特准则:(Law of Demeter LOD)一个目标应该对其他目标有最少的了解。

经过一个ImageLoader的比如来看其间的单一责任准则、开闭准则、依靠倒置准则

该ImageLoader的需求是能够完成图片的加载和缓存。
第一版代码:一个类走全国。

/**
 * 第一版代码: 一个类走全国(运用一个类完成一切的功用)
 */
public class ImageLoader {
    // 图片缓存
    LruCache<String, Bitmap> mImageCache;
    // 线程池
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    Handler mUiHandler = new Handler(Looper.myLooper());
    public ImageLoader(){
        initImageCache();
    }
    private void initImageCache() {
        // 核算运行时可运用的最大内存
        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        // 取四分之一的可用内存作为缓存
        int cacheSize = maxMemory / 4;
        mImageCache = new LruCache<String, Bitmap>(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes() * value.getHeight() /1024;
            }
        };
    }
    public void displayImage(String url,ImageView imageView){
        imageView.setTag(url);
        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = downLoadImage(url);
                if(bitmap == null){
                    return;
                }
                if(imageView.getTag().equals(url)){
                    updateImageView(imageView,bitmap);
                }
                mImageCache.put(url,bitmap);
            }
        });
    }
    private void updateImageView(final ImageView imageView,final Bitmap bitmap){
        mUiHandler.post(new Runnable() {
            @Override
            public void run() {
                imageView.setImageBitmap(bitmap);
            }
        });
    }
    public Bitmap downLoadImage(String imageUrl){
        Bitmap bitmap = null;
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());
            urlConnection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }
}

第一版的代码,像不像咱们刚开端写代码的时分会写出来的代码?耦合严峻,一切的功用在同一个类里边完成,跟着日后功用增多,ImageLoader类会越来越大,代码也越来越杂乱,图片加载体系越来越软弱,改一个功用可能会牵一发起全身。假如遵从单一责任准则,把ImageLoader拆分一下,把各个功用独立出来,各个功用都能独立修正代码,不会相互发生影响。 说干就干,把ImageLoader一拆为二,ImageLoader只担任图片的加载工作,创立一个ImageCache担任图片缓存的逻辑。 如下图所示:

LCODER设计模式一:创建型模式

ImageLoader代码修正如下:

/**
 * 第二版代码:
 * 1.新建一个ImageCache,专门用来处理缓存的逻辑
 * 2.修正ImageLoader的代码,ImageLoader只担任图片显现的逻辑
 */
public class ImageLoader {
    ImageCache mImageCache = new ImageCache();
    // 线程池
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    Handler mUiHandler = new Handler(Looper.myLooper());
    public ImageLoader(){
    }
    public void displayImage(String url,ImageView imageView){
        Bitmap bitmap = mImageCache.get(url);
        if(bitmap != null){
            imageView.setImageBitmap(bitmap);
            return;
        }
        imageView.setTag(url);
        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = downLoadImage(url);
                if(bitmap == null){
                    return;
                }
                if(imageView.getTag().equals(url)){
                    updateImageView(imageView,bitmap);
                    mImageCache.put(url,bitmap);
                }
            }
        });
    }
    private void updateImageView(final ImageView imageView,final Bitmap bitmap){
        mUiHandler.post(new Runnable() {
            @Override
            public void run() {
                imageView.setImageBitmap(bitmap);
            }
        });
    }
    public Bitmap downLoadImage(String imageUrl){
        Bitmap bitmap = null;
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());
            urlConnection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }
}

一起创立一个ImageCache,专门处理图片缓存的逻辑。

public class ImageCache {
    // 图片缓存
    LruCache<String, Bitmap> mImageCache;
    public ImageCache(){
        initImageCache();
    }
    private void initImageCache() {
        // 核算运行时可运用的最大内存
        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        // 取四分之一的可用内存作为缓存
        int cacheSize = maxMemory / 4;
        mImageCache = new LruCache<String, Bitmap>(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes() * value.getHeight() /1024;
            }
        };
    }
    public void put(String url,Bitmap bitmap){
        mImageCache.put(url,bitmap);
    }
    public void get(String url,Bitmap bitmap){
        mImageCache.get(url);
    }
}

上面解决了ImageLoader耦合严峻的问题,可是Android体系应用的内存有限,不行能把图片只存在缓存中,还需求把图片存在SD卡中,跟着业务逻辑的优化,除了MemoryCache,还需求一个DiskCache。

public class DiskCache {
    static String cacheDir = "sdcard/cache/";
    // 从sd卡中获取图片
    public Bitmap get(String url){
        return BitmapFactory.decodeFile(cacheDir + url);
    }
    public void put(String url, Bitmap bmp) {
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(cacheDir + url);
            bmp.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            CloseUtils.closeIO(fileOutputStream);
        }
    }
}

现在项目中有了DiskCache和MemoryCache双缓存,用户就能够先从内存中获取缓存,假如没有再去SD卡中获取缓存,SD卡没有再去网络上下载图片,大大提升了性能,要完成这个需求,就需求一个DoubleCache。这里为了增加代码可读性,把ImageCache更名为MemoryCache。

public class DoubleCache {
    MemoryCache mMemoryCache = new MemoryCache();
    DiskCache mDiskCache = new DiskCache();
    // 先从内存缓存中获取图片,假如没有,再从SD卡中获取
    public Bitmap get(String url){
        Bitmap bitmap = mMemoryCache.get(url);
        if(bitmap == null){
            bitmap = mDiskCache.get(url);
        }
        return bitmap;
    }
    public void put(String url,Bitmap bitmap){
        mMemoryCache.put(url,bitmap);
        mDiskCache.put(url, bitmap);
    }
}

由于需求将图片缓存到SD卡中,ImageLoader的代码也要变:增加

/**
 * 第三版代码:
 * 1.新建一个ImageCache,专门用来处理缓存的逻辑
 *   新增一个DiskCache,增加SD卡缓存
 *   新增双缓存管理类 Double
 * 2.修正ImageLoader的代码,ImageLoader只担任图片显现的逻辑
 *
 */
public class ImageLoader {
    MemoryCache mImageCache = new MemoryCache();
    DiskCache mDiskCache = new DiskCache();
    DoubleCache mDoubleCache = new DoubleCache();
    boolean isUseDoubleCache = false;
    boolean isUseDiskCache = false;
    // 线程池
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    Handler mUiHandler = new Handler(Looper.myLooper());
    public ImageLoader(){
    }
    public void displayImage(String url,ImageView imageView){
        // 判断运用那种缓存
        Bitmap bitmap = null;
        if(isUseDoubleCache){
            bitmap = mDoubleCache.get(url);
        }else if(isUseDiskCache){
            bitmap = mDiskCache.get(url);
        }else{
            bitmap = mImageCache.get(url);
        }
        if(bitmap != null){
            imageView.setImageBitmap(bitmap);
            return;
        }
        imageView.setTag(url);
        mExecutorService.submit(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = downLoadImage(url);
                if(bitmap == null){
                    return;
                }
                if(imageView.getTag().equals(url)){
                    updateImageView(imageView,bitmap);
                    mImageCache.put(url,bitmap);
                }
            }
        });
    }
    private void updateImageView(final ImageView imageView,final Bitmap bitmap){
        mUiHandler.post(new Runnable() {
            @Override
            public void run() {
                imageView.setImageBitmap(bitmap);
            }
        });
    }
    public Bitmap downLoadImage(String imageUrl){
        Bitmap bitmap = null;
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());
            urlConnection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }
    public void setUseDiskCache(boolean useDiskCache){
        this.isUseDiskCache = useDiskCache;
    }
    public void setUseDoubleCache(boolean useDoubleCache){
        this.isUseDoubleCache = useDoubleCache;
    }
}

上面的代码的确解决了双缓存的问题,可是,现在问题又来了,便是用户每增加一种缓存的办法,就需求去修正ImageLoader的代码,这显然是不合理的。 假如此刻咱们遵从开闭准则,当软件需求改变时,尽量经过扩展的办法来完成改变,而不是经过修正已有的代码来完成,那么代码的可扩展性就会很强。 如下图所示:

LCODER设计模式一:创建型模式
界说一个接口ImageCache,这个接口中界说get和put办法,MemoryCache、DiskCache、DoubleCache都完成这个接口。

public interface ImageCache {
    public void put(String url, Bitmap bitmap);
    public Bitmap get(String url);
}
public class MemoryCache implements ImageCache{
    // 图片缓存
    LruCache<String, Bitmap> mImageCache;
    public MemoryCache(){
        initMemoryCache();
    }
    private void initMemoryCache() {
        // 核算运行时可运用的最大内存
        int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        // 取四分之一的可用内存作为缓存
        int cacheSize = maxMemory / 4;
        mImageCache = new LruCache<String, Bitmap>(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes() * value.getHeight() /1024;
            }
        };
    }
    public void put(String url,Bitmap bitmap){
        mImageCache.put(url,bitmap);
    }
    public Bitmap get(String url){
        return mImageCache.get(url);
    }
}
public class DiskCache implements ImageCache{
    static String cacheDir = "sdcard/cache/";
    // 从sd卡中获取图片
    public Bitmap get(String url){
        return BitmapFactory.decodeFile(cacheDir + url);
    }
    public void put(String url, Bitmap bmp) {
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(cacheDir + url);
            bmp.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            CloseUtils.closeIO(fileOutputStream);
        }
    }
}
public class DoubleCache implements ImageCache{
    MemoryCache mMemoryCache = new MemoryCache();
    DiskCache mDiskCache = new DiskCache();
    // 先从内存缓存中获取图片,假如没有,再从SD卡中获取
    public Bitmap get(String url){
        Bitmap bitmap = mMemoryCache.get(url);
        if(bitmap == null){
            bitmap = mDiskCache.get(url);
        }
        return bitmap;
    }
    public void put(String url,Bitmap bitmap){
        mMemoryCache.put(url,bitmap);
        mDiskCache.put(url, bitmap);
    }
}

在ImageLoader中增加一个setImageCache(ImageCache)办法,运用哪种缓存办法就传入哪种缓存办法。

/**
 * 第四版代码:
 * 1.创立一个接口ImageCache MemoryCache、DiskCache、DoubleCache都完成这个接口。
 * 2.ImageLoader里边增加一个设置ImageCache的办法,运用哪种缓存办法就传入哪种缓存办法。
 */
public class ImageLoader {
    ImageCache mCache = new MemoryCache();
    // 线程池
    ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    Handler mUiHandler = new Handler(Looper.myLooper());
    public ImageLoader(){
    }
    public void displayImage(String url,ImageView imageView){
        Bitmap bmp = mCache.get(url);
        if (bmp == null) {
            downloadImageAsync(url, imageView);
        } else {
            imageView.setImageBitmap(bmp);
        }
    }
    private void downloadImageAsync(String url, ImageView imageView) {
        Bitmap bmp = downLoadImage(url);
        mCache.put(url, bmp);
        imageView.setImageBitmap(bmp);
    }
    private void updateImageView(final ImageView imageView,final Bitmap bitmap){
        mUiHandler.post(new Runnable() {
            @Override
            public void run() {
                imageView.setImageBitmap(bitmap);
            }
        });
    }
    public Bitmap downLoadImage(String imageUrl){
        Bitmap bitmap = null;
        try {
            URL url = new URL(imageUrl);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            bitmap = BitmapFactory.decodeStream(urlConnection.getInputStream());
            urlConnection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }
    /**
     * 设置缓存战略
     *
     * @param cache 缓存
     */
    public void setImageCache(ImageCache cache) {
        mCache = cache;
    }
}

经过上面的改造,现在用户就算想要增加一种缓存战略,也不需求再修正ImageLoader,只需求增加一种缓存办法,并完成ImageCache即可。这就遵从了开闭准则:对扩展敞开,对修正封闭。 另外,在上面的ImageLoader中,咱们创立了一个缓存类ImageCache。这个当地遵从了依靠倒置准则,图片缓存类,依靠于笼统,并且有一个默认的完成。

 ImageCache mCache = new MemoryCache();

经过这个比如,咱们初步的了解了面向目标的三大准则,初尝了规划形式的好处,代码也在几回的修正之后,变得愈加的健壮。

下面就开端规划形式之旅吧。

创立型形式

1.工厂办法形式

工厂办法形式,是Java中最常用的规划形式之一。详细的界说便是:界说一个用于创立目标的接口,让子类决定实例化哪个工厂类。 完成: 咱们创立一个Furit接口和完成Furit接口的实体类。创立一个生果工厂类FuritFactory。如下图所示:

LCODER设计模式一:创建型模式
创立一个接口Fruit。创立Apple和Banana完成这个接口。

public interface Fruit {
    void print();
}
public class Apple implements Fruit{
    @Override
    public void print() {
        System.out.print("Apple");
    }
}
public class Banana implements Fruit{
    @Override
    public void print() {
        System.out.printf("Banana");
    }
}

创立一个工厂,生成生果。

public class FruitFactory {
    public Fruit getFruit(String type){
        if(type == null){
            return null;
        }
        if(type.equalsIgnoreCase("APPLE")){
            return new Apple();
        } else if(type.equalsIgnoreCase("BANANA")){
            return new Banana();
        }
        return null;
    }
}

需求哪种生果,就传入哪种生果的类型即可,这种办法比较简洁,像这样的办法又称为简略工厂形式或者是静态工厂形式,它是工厂形式的一个弱化版别。 总得来说,工厂办法形式是一个很好的规划形式,但其缺陷也是显而易见的,每次增加新产品时,就要编写一个新的产品类。这必然会导致类的结构杂乱化,所以,在某些情况比较简略是,是否运用工厂形式,就需求权衡利弊了。

2. 笼统工厂形式

笼统工厂形式,是环绕一个超级工厂创立其他工厂。它的界说是:为创立一组相关或者是相互依靠的目标提供一个接口,而不需求指定它们的详细类。 完成:创立一个超级生果工厂,这个工厂既能够生成苹果也能够生成香蕉,再分别创立一个苹果工厂和香蕉工厂,承继自这个超级生果工厂,苹果工厂只出产苹果,香蕉工厂只出产香蕉。UML图如下图所示:

LCODER设计模式一:创建型模式
创立笼统的苹果类,这个类有红苹果和青苹果两个子类。 创立笼统的香蕉类,这个类有黄香蕉和青香蕉两个子类。

public abstract class AbstractApple {
   public abstract void print();
}
public class RedApple extends AbstractApple{
    @Override
    public void print() {
        System.out.printf("RedApple");
    }
}
public class GreenApple extends AbstractApple{
    @Override
    public void print() {
        System.out.printf("GreenApple");
    }
}
public abstract class AbstractBanana {
    public abstract void print();
}
public class YellowBanana extends AbstractBanana{
    @Override
    public void print() {
        System.out.printf("YellowBanana");
    }
}
public class GreenBanana extends AbstractBanana{
    @Override
    public void print() {
        System.out.printf("GreenBanana");
    }
}

创立一个超级生果工厂类,这个类有两个子类,苹果工厂类和香蕉工厂类

public abstract class AbstractFruitFactory {
    public abstract Apple getApple();
    public abstract Banana getBanana();
}

出产苹果的工厂只完成出产苹果的办法。

public class AppleFactory extends AbstractFruitFactory{
    @Override
    public Apple getApple() {
        return new Apple();
    }
    @Override
    public Banana getBanana() {
        return null;
    }
}

出产香蕉的工厂只完成出产香蕉的办法。

public class BananaFactory extends AbstractFruitFactory{
    @Override
    public Apple getApple() {
        return null;
    }
    @Override
    public Banana getBanana() {
        return new Banana();
    }
}

以上,就完成了一个笼统工厂形式。 笼统工厂办法形式的优点:别离了接口与完成,而缺陷也十分的显而易见,便是类文件的爆炸性增加,不太简略扩展新的产品类,每增加一个产品类就需求修正笼统工厂,一切的详细完成都会被修正。

3. 单例形式

单例形式,是Java规划形式中最简略的规划形式之一。它的界说是:保证一个类只有一个实例,而且自行实例化并向整个体系提供整个实例。 完成:UML图如下所示:

LCODER设计模式一:创建型模式

单例形式的几种完成:

1、饿汉式

这种办法比较常用,但简略发生废物目标。这种办法便是在类加载时就创立实例,糟蹋内存。

public class Singleton {
   private static Singleton instance = new Singleton(); 
   private Singleton (){
     }
   public static Singleton getInstance() { 
         return instance; 
     } 
   }

2、懒汉式

这种办法便是在运用时才创立实例。

public class Singleton {
    private static Singleton instance;
    private Singleton (){}
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

这种完成最大的问题是线程不安全,没有加锁synchronized。严厉意义上,它并不能算单例形式。

3、懒汉式(线程安全)

这种办法是线程安全的,能在多线程中很好的工作,保证在多线程中只会发生一个实例,可是,功率很低,由于客户端99%不需求同步。

public class Singleton {
    private static Singleton instance;
    private Singleton (){}
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

4、DCL(Double Check Lock)两层校验锁

这种办法既能保证线程安全,且当有两个线程一起调用new Singleton()时,假如第一个线程已经创立了Singleton实例,第二个线程等候第一个线程履行完成后进入第二重锁中发现singleton不为空,直接回来singleton,节省资源。 其间运用volatile关键字,是为了保证每次获取singleton目标都是从主内存中获取,防止DCL失效的问题。

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton (){}
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

5、静态内部类单例形式。

这种办法是最推荐运用的单例形式的完成办法。
这种办法的原理是:当调用getInstance()时,会调用SingletonHolder.INSTANCE,此刻SingletonHolder才会初始化,这是由于当类初始化时,其静态域也会初始化,由所以静态的,JVM只会加载一次,JVM保证了线程安全。

public class Singleton {
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    private Singleton (){}
    public static final Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

6、枚举单例

这种办法最简洁,一起由于默认枚举实例的创立是线程安全的,并且在任何情况下,枚举实例都是一个单例,这种办法其实是最好的单例的完成办法。

public enum Singleton {
    INSTANCE;
    public void dosth() {
        System.out.printf("do sth");
    }
}

4. 制作者形式 (Builder形式)

运用多个简略的目标一步一步构建成一个杂乱的目标。这种规划形式,能够讲一个杂乱的构建与其表明相别离,使得通用的构建进程能够创立不同的表明。 完成:UML图如下所示:

LCODER设计模式一:创建型模式
一个简略的拼装电脑的进程,首要创立一个Computer类(Product)

public abstract class Computer {
    protected String mBoard; // 主板
    protected String mDisplay; // 显现器
    protected String mOS; // 操作体系
    protected Computer(){
    }
    // 设置主板
    public void setBoard(String board) {
        this.mBoard = board;
    }
    // 设置显现器
    public void setDisplay(String display) {
        this.mDisplay = display;
    }
    // 设置操作体系
    public void setOS();
    @Override
    public String toString() {
        return "Computer{" +
                "mBoard='" + mBoard + ''' +
                ", mDisplay='" + mDisplay + ''' +
                ", mOS='" + mOS + ''' +
                '}';
    }
}

一个详细的电脑:MacBook承继自Computer

public class MacBook extends Computer{
    protected MacBook(){
    }
    @Override
    public void setOS() {
        mOS = "MAC OS";
    }
}

创立Builder类

public abstract class Builder {
    // 设置主板
    public abstract void buildBoard(String board);
    // 设置显现器
    public abstract void buildDisplay(String display);
    // 设置操作体系
    public abstract void buildOS();
    // 创立Computer
    public abstract Computer createComputer();
}

详细的Builder类,MacBookBuilder

public class MacBookBuilder extends Builder{
    private Computer mComputer = new MacBook();
    @Override
    public void buildBoard(String board) {
        mComputer.setBoard(board);
    }
    @Override
    public void buildDisplay(String display) {
        mComputer.setDisplay(display);
    }
    @Override
    public void buildOS() {
        mComputer.setOS();
    }
    @Override
    public Computer createComputer() {
        return mComputer;
    }
}

Director类,担任结构Computer

public class Director {
    Builder mBuilder = null;
    public Director(Builder builder){
        mBuilder = builder;
    }
    public void construct(String board,String display){
        mBuilder.buildBoard(board);
        mBuilder.buildDisplay(display);
        mBuilder.buildOS();
    }
}

运用制作者形式,创立MacBook。

public static void main(String[] args) {
    Builder builder = new MacBookBuilder();
    Director director = new Director(builder);
    director.construct("英特尔","惠普显现器");
}

在上面的比如中,经过详细的MacBookBuilder来构建了MacBook目标,而Director封装了构建杂乱产品目标的进程,对外躲藏构建细节。Builder与Director曾经讲一个杂乱目标的构建与它的表明别离,使得相同的构建进程能够创立不同的目标。