简单工厂模式

1. 定义:

  • 属于创建型模式,又叫做静态工厂方法,但不属于23种GOF设计模式之一。
  • 由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
  • 将“类实例化的操作”与“使用对象的操作”分开,让使用者不用知道具体参数就可以实例化出所需要的“产品”类,从而避免了在客户端代码中显式指定,实现了解耦。

2. 适用场景:

  • 工厂类负责创建的对象比较少;
  • 客户只知道传入工厂类的参数,对于如何创建对象(逻辑)不关心;
  • 由于简单工厂很容易违反高内聚责任分配原则,因此一般只在很简单的情况下应用;

3. 优缺点:

  • 优点:通过使用工厂类,调用者仅仅需要负责“消费”对象就可以了。而不必管这些对象究竟如何创建及如何组织的,明确了各自的职责和权利,有利于整个软件体系结构的优化。
  • 缺点:由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。当系统中的具体产品类不断增多时候,可能会出现要求工厂类根据不同条件创建不同实例的需求.这种对条件的判断和对具体产品类型的判断交错在一起,很难避免模块功能的蔓延,对系统的维护和扩展非常不利;
  • 这些缺点在 工厂方法模式 中得到了一定的克服。

4. Android源码中的体现

如创建Bitmap对象的时候,例如通过资源id获取Bitmap对象:

Bitmap bitmap=BitmapFactory.decodeResource(
      getResources(), R.drawable.ic_launcher);

5. 实例演示:

以宠物店买猫为例

  1. 首先创建一个抽象类cat
abstract class Cat {
        public abstract void show();
    }
  1. 然后创建两个子类,波斯猫和虎斑猫
class CatA extends Cat {
        @Override
        public void show() {
            LjyLogUtil.i("A-波斯猫:喵喵喵~");
        }
    }

class CatB extends Cat {
        @Override
        public void show() {
            LjyLogUtil.i("B-虎斑猫:喵喵喵~~~");
        }
    }
  1. 创建工厂类CatFactory,提供了两种猫咪可选,客户只需要知道想买什么品种的猫,而不需要关心他是如何产生的,这是简单工厂模式的核心
class CatFactory {
        public enum CatType {
            TYPE_A,
            TYPE_B
        }

        public static Cat newCat(CatType catType) {
            switch (catType) {
                case TYPE_A:
                    return new CatA();
                case TYPE_B:
                    return new CatB();
                default:
                    return null;
            }
        }
    }
  1. 最后就是在使用工厂类创建cat实例了
 private void methodSimpleFactoryPattern() {
        CatFactory.newCat(CatFactory.CatType.TYPE_A).show();
        CatFactory.newCat(CatFactory.CatType.TYPE_B).show();
//        try {
//            CatFactory.newCat(2).show();
//        } catch (NullPointerException e) {
//            LjyLogUtil.i("没有这一类Cat");
//        }
    }

工厂方法模式

1. 定义:

又称工厂模式、多态工厂模式和虚拟构造器模式;

此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂,具体工厂,抽象产品,具体产品;

简单工厂的弊端: 1.工厂类集中了所有实例(产品)的创建逻辑,一旦这个工厂不能正常工作,整个系统都会受到影响; 2.违背“开放 - 关闭原则”,一旦添加新产品就不得不修改工厂类的逻辑,这样就会造成工厂逻辑过于复杂; 3.简单工厂模式由于使用了静态工厂方法,静态方法不能被继承和重写,会造成工厂角色无法形成基于继承的等级结构; 工厂方法模式如何解决上述问题:

工厂方法模式把具体产品的创建推迟到工厂类的子类(具体工厂)中,此时工厂类不再负责所有产品的创建,而只是给出具体工厂必须实现的接口;

2. 适用场景

对于某个产品,调用者清楚地知道应该使用哪个具体工厂服务,实例化该具体工厂,生产出具体的产品来。Java Collection中的iterator() 方法即属于这种情况。

只是需要一种产品,而不想知道也不需要知道究竟是哪个工厂为生产的,即最终选用哪个具体工厂的决定权在生产者一方,它们根据当前系统的情况来实例化一个具体的工厂返回给使用者,而这个决策过程对于使用者来说是透明的。

3. Android源码中的体现

如常用的Retrofit中的Converter.Factory ,CallAdapter.Factory即为抽象工厂类,它们的子类即为具体工厂类:

 private RetrofitUtil() {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BaseUrl.getBaseUrl())
                //配置okhttp
                .client(getOkHttpClient())
                //支持gson
                .addConverterFactory(GsonConverterFactory.create())
                //增加返回值为Oservable<T>的支持,RxJava
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
        apiService = retrofit.create(ApiService.class);
    }

3. 实例演示

以宠物店买鸭子为例

  1. 创建抽象鸭子类
abstract class Duck {
        public abstract void show();
    }
  1. 创建两个鸭子子类
class DuckA extends Duck {

        @Override
        public void show() {
            LjyLogUtil.i("DuckA:呀呀呀~");
        }
    }

    class DuckB extends Duck {

        @Override
        public void show() {
            LjyLogUtil.i("DuckB:呀呀呀~");
        }
    }

前面这两步和简单工厂模式是一样的,工厂方法模式相对于简单工厂模式的最大优点就在于工厂类的可扩展性

  1. 创建抽象工厂类
 abstract class DuckFactory {
        public abstract Duck newDuck();
 }
  1. 创建两个具体工厂类
class DuckAFactory extends DuckFactory {

        @Override
        public Duck newDuck() {
            return new DuckA();
        }
    }

    class DuckBFactory extends DuckFactory {

        @Override
        public Duck newDuck() {
            return new DuckB();
        }
    }

  1. 具体使用
private void methodFactoryMethod() {
        DuckAFactory duckAFactory = new DuckAFactory();
        duckAFactory.newDuck().show();

        DuckBFactory duckBFactory = new DuckBFactory();
        duckBFactory.newDuck().show();
    }
  1. 也可以像下面这样用反射创建工厂类(需要知道要创建的具体实现类,耦合度高)
class DuckFactort {
        public <T extends Duck> T get(Class<T> duckClass) {
            try {
                Duck duck = (Duck) Class.forName(duckClass.getName()).newInstance();
                return (T) duck;
            } catch (Exception e) {
                return null;
            }
        }
    }

我是今阳,如果想要进阶和了解更多的干货,欢迎关注公众号”今阳说“接收我的最新文章

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐