x工厂模式、抽象工厂

学习自

http://baijiahao.baidu.com/s?id=1586800950048933907&wfr=spider&for=pc

何为工厂?

戴尔电脑

public class DellComputer {
    private String computerName;
}

戴尔电脑工厂

public class DellComputerFactory {
    public DellComputer createDellComputer() {
        return new DellComputer();
    }
}

代码中如何调用

DellComputerFactory dellComputerFactory = new DellComputerFactory();
dellComputerFactory.createDellComputer();

其实可以看到, 使用工厂前和使用工厂后,我们创建对象的过程发生了怎样的转变呢?

new DellComputer();——>new DellComputerFactory().createDellComputer();

之所以有工厂模式的存在, 也就是说,创造 这个模式的人,认为创建对象的这个过程,是可以被抽象的。也就是说,创造这个模式的人, 认为

1.创建一个对象 是复杂的

2.创建一个 对象虽然复杂, 但是却是有规律可循的

3.创建一个对象是频繁的,不易于修改的,我们可以用工厂避免 频繁的修改,带来的巨大的工作量

怎么去理解这3句话呢?我们可以用Java线程池来弄清这一点

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
}

这么长的参数,可想而知其 复杂性。熟悉线程池的人会知道,这些参数的含义:

1.核心线程数量

2.最大线程数量(=核心线程数量+非核心线程数量)

3.非核心线程保活时间

4.时间单位

5.阻塞队列

6.线程工厂,也就是说我们可以自己定义创建一个线程的逻辑

7.拒绝策略

可想而知,我们需要进行一系列复杂的配置才能有效地使用它。但是:

1.这些东西写在比如Activity里会很不美观,其实我们 只需要知道他做了 什么事就可以了。业务和框架应该是抽离的。

2. 这些东西改动起来太麻烦

3.往往一个项目某一个业务模块使用的线程池是一致的,所以完全可以 抽象出来。

可以看到Android 线程池已经提供了一些默认的工厂实现

public class Executors {

    public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

    public static ExecutorService newWorkStealingPool(int parallelism) {
        return new ForkJoinPool
            (parallelism,
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

    public static ExecutorService newWorkStealingPool() {
        return new ForkJoinPool
            (Runtime.getRuntime().availableProcessors(),
             ForkJoinPool.defaultForkJoinWorkerThreadFactory,
             null, true);
    }

    public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>(),
                                      threadFactory);
    }

    public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }

比如第一个定长线程池

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

可以看到核心线程池就是只有核心线程的线程池。他把原来的 线程池抽象成了一个只有 核心线程的线程池。

我们可以从中借鉴的第一点:我们也可以学着 这样,把自己项目用到的线程池,全部封装到这里面。

我们可以从中借鉴的第二点:工厂模式可以在原有的基础上再度简化。Android源码中处处都应用了设计模式,不仅如此, 他在原有的基础上做的 更加简洁。比如这里的工厂方法, 直接弄成静态;比如建造者模式,他舍弃了冗余的构建,采用简洁的链式调用。

所以根据第二点,我们的工厂可以这样 改造:

public class DellComputerFactory {
    public static DellComputer createDellComputer() {
        return new DellComputer();
    }
}

再根据第一点,我们的工厂可以 这样改造:

public class ComputerFactory {
    
    public static DellComputer createDellComputer() {
        return new DellComputer();
    }
    
    public static MSIComputer createMSIComputer() {
        return new MSIComputer();
    }
}

在优化一点点

public class Computer {

    private String computerName;

    public Computer(String computerName) {
        this.computerName = computerName;
    }
}
public class ComputerFactory {

    public static Computer createDellComputer() {
        return new Computer("dell computer");
    }

    public static Computer createMSIComputer() {
        return new Computer("msi computer");
    }
}

接下来使用

Computer dellComputer = ComputerFactory.createDellComputer();
Computer msiComputer = ComputerFactory.createMSIComputer();

再次感叹Android的源码水平境界之高。探索到这里结束,进入工厂正文。同时我们也可以认识到了,工厂并不是那么看起来的没有用,只是我们往往忽视了它罢了。

实际上,未简化版的工厂模式 要冗余的多

他需要有

1.抽象产品

public abstract class AbstractComputer {
    public abstract void getComputerName();
}

2.实际产品

public class DellComputer extends AbstractComputer{
    @Override
    public void getComputerName() {
        System.out.println("dell computer");
    }
}
public class MSIComputer extends AbstractComputer{
    @Override
    public void getComputerName() {
        System.out.println("msi computer");
    }
}

3.抽象工厂

public abstract class AbstractComputerFactory {
    public abstract AbstractComputer createComputer();
}

4.实际工厂

public class DellComputerFactory extends AbstractComputerFactory{
    @Override
    public AbstractComputer createComputer() {
        return new DellComputer();
    }
}
public class MSIComputerFactory extends AbstractComputerFactory {
    @Override
    public AbstractComputer createComputer() {
        return new MSIComputer();
    }
}

所以我们现在 创建实例是这样的

AbstractComputerFactory computerFactory = new MSIComputerFactory();
computerFactory.createComputer();

AbstractComputerFactory computerFactory1 = new DellComputerFactory();
computerFactory1.createComputer();

反射工厂

原来我们有两种 工厂

1.抽象工厂

2.具体工厂

我们具体工厂在继承了抽象工厂以后,通过new的形式来创建实例。其实对于创建实例,不仅仅只是new一种方法,也可以通过 反射方式创建实例。

所以把抽象工厂类改写一下

public class ComputerFactory {
    public <T extends AbstractComputer> AbstractComputer createComputer(Class<T> computerClass) {
        try {
            Object computer = computerClass.newInstance();
            return (AbstractComputer) computer;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        
        return null;
    }
}

所以现在是 这样创建实例的

ComputerFactory computerFactory = new ComputerFactory();
MSIComputer msiComputer = computerFactory.createComputer(MSIComputer.class);
DellComputer dellComputer = computerFactory.createComputer(DellComputer.class);

而且原有的具体工厂都不必再写了

总结下工厂模式,方便记忆

本来是直接MSI工厂创建MSI电脑即可,现在是通过抽象父类,让我们隔绝了细节,相当于降低了耦合。

抽象工厂

比工厂模式要难理解一点,不过是面试官的常考点之一。

 可以通过这样一张图去理解

这里我们就有了对这个工厂的定义了:这个工厂可以生产A、B两种产品,A和B都有多种实现。

比如我们这里是MSI电脑工厂,那么A可以是一种MSI机型,B是另一种MSI机型吗?不行,因为这里是抽象的工厂,所以的工厂都需要创建同类的产品,如果把A、B产品定义成某机型, 只能对于MSI适用。所以这里的东西应该是所以电脑公有的东西。 所以这里不应该是机型,而是比如A是低配电脑,B是高配电脑。

 总结一下, 在这里就是: 这里是电脑工厂,我们生产产品A是低配电脑,B是高配 电脑。具体的第一个实现类,MSI电脑,我们的生产产品A是MSI低配电脑,B是MSI高配电脑。第二个实现类,DELL电脑,我们的生产产品A是DELL低配电脑,B是DELL高配电脑。以此类推。

这就是抽象工厂的含义,比如这里抽象的是电脑,然后创建的产品, 必定是所有电脑的共性产品,低配电脑,高配电脑。

工厂模式和抽象工厂的区别

前者 

一步步来一遍,为了方便记忆

一开始是最简单的new

public class MSIComputer {
}
MSIComputer msiComputer = new MSIComputer();

后来用最简单的工厂封装一下

public class MSIComputerFactory {
    public MSIComputer createMSIComputer() {
        return new MSIComputer();
    }
}
MSIComputerFactory msiComputerFactory = new MSIComputerFactory();
MSIComputer msiComputer = msiComputerFactory.createMSIComputer();

工厂模式,弄出产品和工厂的抽象类,然后就不是直接的耦合了

public interface IComputer {
}
public interface IComputerFactory {
    IComputer createComputer();
}
public class MSIComputer implements IComputer{
}
public class MSIComputerFactory implements IComputerFactory{
    @Override
    public IComputer createComputer() {
        return new MSIComputer();
    }
}
IComputerFactory computerFactory = new MSIComputerFactory();
IComputer iComputer = computerFactory.createComputer();

抽象工厂。 上面的是工厂模式,只生产电脑; 如果是抽象工厂,会生产好电脑,差电脑。

1.电脑抽象

public interface IComputer {
}

2.坏电脑抽象

public class IBadComputer implements IComputer{
}

3.好电脑抽象

public interface IGoodComputer extends IComputer{
}

4.MSI坏电脑

public class MSIBadComputer implements IBadComputer{
}

5.MSI好电脑

public class MSIGoodComputer implements IGoodComputer{
}

6.DELL坏电脑

public class DELLBadComputer implements IBadComputer {
}

7.DELL好电脑

public class DELLGoodComputer implements IGoodComputer{
}

8.电脑工厂

public interface IComputerFactory {

    IComputer createGoodComputer();

    IComputer createBadComputer();
}

9.MSI电脑工厂

public class MSIComputerFactory implements IComputerFactory{
    @Override
    public IComputer createGoodComputer() {
        return new MSIGoodComputer();
    }

    @Override
    public IComputer createBadComputer() {
        return new MSIBadComputer();
    }
}

10.DELL电脑工厂

public class DELLComputerFactory implements IComputerFactory{
    @Override
    public IComputer createGoodComputer() {
        return new DELLGoodComputer();
    }

    @Override
    public IComputer createBadComputer() {
        return new DELLBadComputer();
    }
}

11.最终使用

IComputerFactory computerFactory = new MSIComputerFactory();
IComputer computer = computerFactory.createBadComputer();
IComputer computer1 = computerFactory.createGoodComputer();

IComputerFactory computerFactory1 = new DELLComputerFactory();
IComputer computer2 = computerFactory1.createGoodComputer();
IComputer computer3 = computerFactory1.createBadComputer();

猜你喜欢

转载自blog.csdn.net/qq_36523667/article/details/81268895