likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 72

本文目录: 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以前讲一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的对象。

转载自:https://juejin.cn/post/7130916808055324686
评论
请登录