23种设计模式之工厂模式

记录自己对工厂模式的理解,如有不对的地方,请大家多多包涵,帮忙指出。

作用:实现了创建者和调用者的分离。

本文主要分三类:
1.简单工厂
2.工厂方法
3.抽象工厂

简单工厂

本人挺喜欢牛仔裤的,我就以牛仔裤做例子吧,先从没有工厂模式的情况下创建一条牛仔裤。
先创建一个牛仔裤的接口Jeans

public interface Jeans {
    void wear();
}

现在创建两个品牌的牛仔裤的实体类,实现Jeans接口

import android.util.Log;

/**
 * 这是JEE牛仔裤.
 */

public class JeansJee implements Jeans {
    @Override
    public void wear() {
        Log.d("TAG", "JEE牛仔裤穿起来就是潮");
    }
}
import android.util.Log;

/**
 *这是Levis牛仔裤
 */

public class JeansLevis implements Jeans {
    @Override
    public void wear() {
        Log.d("TAG","李维斯牛仔裤穿起来就是经典");
    }
}

现在我们试试没有工厂模式的情况下调用

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import com.hdc.test.simple.Jeans;
import com.hdc.test.simple.JeansJee;
import com.hdc.test.simple.JeansLevis;

/**
 * 这是调用者
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //调用JEE牛仔裤
        Jeans jee = new JeansJee();
        jee.wear();

        //调用Levis牛仔裤
        Jeans levis = new JeansLevis();
        levis.wear();

    }
}
image.png

这样写也可以啊,为什么要使用工厂呢?比如我是调用者,我想要一条Levis牛仔裤和一条Jee牛仔裤,但是我得知道怎么创建Levis牛仔裤和Jee牛仔裤,是不是就得去和实体类打交道?才能创建出来穿上?拜托,我只是一个调用者,我才不想知道这些过程,我只知道裤子能穿,其他的我才懒得管,这下工厂是不是就有它的价值了?我只需要让工厂去帮我创建就好了,并且这种写法也已经违反了设计模式六大原则中的依赖倒置原则(要针对抽象编程,而不是针对实现细节编程),下面我们创建一个工厂,在有工厂的情况下是一个什么情景。

首先我们先创建一个工厂:

/**
 * 这是牛仔裤制造工厂
 * 简单工厂也称为静态工厂
 */

public class JeansFactory {

    public static Jeans jee() {
        return new JeansJee();
    }

    public static Jeans levis() {
        return new JeansLevis();
    }
}

然后在有简单工厂模式的情况下调用

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.hdc.test.simple.Jeans;
import com.hdc.test.simple.JeansFactory;

/**
 *这是调用者
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//        //没有工厂的情况下调用
//        //调用JEE牛仔裤
//        Jeans jee = new JeansJee();
//        jee.wear();
//
//        //调用Levis牛仔裤
//        Jeans levis = new JeansLevis();
//        levis.wear();
        
        //有工厂的情况下调用
        //调用JEE牛仔裤
        Jeans jee = JeansFactory.jee();
        jee.wear();
        
        //调用Levis牛仔裤
        Jeans levis = JeansFactory.levis();
        levis.wear();

    }
}
image.png

这样我们是不是不需要直接和实体类打交道了?把所有一切都交给工厂,只需要告诉工厂说我需要JEE或者Levis就行了,这就符合先前说的依赖倒置原则了,但是简单工厂还是有缺点,因为这违反了设计模式六大原则中的开闭原则(对于扩展是开放的,对于修改是关闭的),这点缺点如果不是开发JDK啊这些不是什么问题,所以一般项目用简单工厂还是比较多的,为了弥补这个缺陷,工厂方法就有存在的价值了,下面我们来看看工厂方法怎么做。

工厂方法

老样子,先把牛仔裤接口和实体类建出来,先建牛仔裤接口

/**
 *这是一个牛仔裤接口
 *
 */

public interface Jeans {
    void wear();
}

创建Jee牛仔裤实体类并实现Jeans接口

import android.util.Log;

/**
 * 这是JEE牛仔裤
 */

public class JeansJee implements Jeans {
    @Override
    public void wear() {
        Log.d("TAG", "JEE牛仔裤穿起来就是潮");
    }
}

创建Levis牛仔裤实体类并实现Jeans接口

import android.util.Log;

/**
 *这是Levis牛仔裤
 */

public class JeansLevis implements Jeans {
    @Override
    public void wear() {
        Log.d("TAG","李维斯牛仔裤穿起来就是经典");
    }
}

好了,现在牛仔裤接口和牛仔裤实体类都有了,现在开始建工厂,首先得先创建一个工厂接口,在里边定义一个牛仔裤品牌工厂的方法

/**
 * 这是一个工厂接口
 */

public interface JeansFactory {
    Jeans jeansBrandFactory();
}

创建JEE工厂,并实现JeansFactory 接口

/**
 * 这是一个JEE工厂
 */

public class JeeFactory implements JeansFactory {
    @Override
    public Jeans jeansBrandFactory() {
        return new JeansJee();
    }
}

再创建一个Levis工厂,,并实现JeansFactory 接口

/**
 * 这是一个Levis工厂
 */

public class LevisFactory  implements JeansFactory{

    @Override
    public Jeans jeansBrandFactory() {
        return new JeansLevis();
    }
}

现在所有的都创建完成了,在有工厂方法的情况下这样调用

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.hdc.test.factorymethod.Jeans;
import com.hdc.test.factorymethod.JeeFactory;
import com.hdc.test.factorymethod.LevisFactory;

/**
 *这是调用者
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//        //没有工厂的情况下调用
//        //调用JEE牛仔裤
//        Jeans jee = new JeansJee();
//        jee.wear();
//
//        //调用Levis牛仔裤
//        Jeans levis = new JeansLevis();
//        levis.wear();

        //简单工厂的情况下调用
        //调用JEE牛仔裤
//        Jeans jee = JeansFactory.jee();
//        jee.wear();
//
//        //调用Levis牛仔裤
//        Jeans levis = JeansFactory.levis();
//        levis.wear();

        //工厂方法情况下调用
        //调用JEE牛仔裤
        Jeans jee = new JeeFactory().jeansBrandFactory();
        jee.wear();

        //调用Levis牛仔裤
        Jeans levis = new LevisFactory().jeansBrandFactory();
        levis.wear();

    }
}
23种设计模式之工厂模式_第1张图片
image.png

使用工厂方法的好处就在于符合了文章开头的开闭原则,如果我需要加一个G-STAR品牌的牛仔裤,我只需要直接加就行了,不需要修改原有代码,这样去加:
先创建一个G-star实体类,并实现Jeans接口

import android.util.Log;

/**
 * 这是G-star牛仔裤
 */

public class JeansGstar implements Jeans {
    @Override
    public void wear() {
        Log.d("TAG","G-STAR牛仔裤穿起来就是舒服");
    }
}

然后创建一个G-star工厂,并实现JeansFactory 接口

/**
 * 这是一个G-star工厂
 */

public class GstarFactory implements JeansFactory {
    @Override
    public Jeans jeansBrandFactory() {
        return new JeansGstar();
    }
}

这样就添加完成了,不需要修改原有代码,已经符合开闭原则(对于扩展是开放的,对于修改是关闭的),调用试试。

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.hdc.test.factorymethod.GstarFactory;
import com.hdc.test.factorymethod.Jeans;
import com.hdc.test.factorymethod.JeeFactory;
import com.hdc.test.factorymethod.LevisFactory;

/**
 *这是调用者
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//        //没有工厂的情况下调用
//        //调用JEE牛仔裤
//        Jeans jee = new JeansJee();
//        jee.wear();
//
//        //调用Levis牛仔裤
//        Jeans levis = new JeansLevis();
//        levis.wear();

        //简单工厂的情况下调用
        //调用JEE牛仔裤
//        Jeans jee = JeansFactory.jee();
//        jee.wear();
//
//        //调用Levis牛仔裤
//        Jeans levis = JeansFactory.levis();
//        levis.wear();

        //工厂方法情况下调用
        //调用JEE牛仔裤
        Jeans jee = new JeeFactory().jeansBrandFactory();
        jee.wear();

        //调用Levis牛仔裤
        Jeans levis = new LevisFactory().jeansBrandFactory();
        levis.wear();

        //调用新增品牌G-star牛仔裤
        Jeans gstar = new GstarFactory().jeansBrandFactory();
        gstar.wear();

    }
}
23种设计模式之工厂模式_第2张图片
image.png

是不是很简单?但是这种写法符合设计模式原则了,但是就真的好吗?它也是有弊端的,对比简单工厂来说,结构更复杂,因为它多出了很多的文件,造成冗余,对于其实两种模式都有自己的优点和缺点,开发时候还得按情况而定。

现在有一种情况是这样的,一件牛仔裤,我需要私人定制怎么办?比如我需要高端的布料,但是纽扣和拉链我只需要低端的就好,或者我需要低端布料,高端纽扣拉链,像这种自由组合,怎么办?但是这个工厂只生产高端产品或者低端产品,我是不是还要找其他工厂去做我想要的?这就涉及三个模式中最复杂的抽象工厂了。

抽象工厂

前提:抽象工厂是新增产品族的,而简单工厂和工厂方法是直接新增产品的,打个比方,抽象工厂就是做牛仔裤的零件的,比如布料、纽扣、拉链就是牛仔裤这个产品的产品族,而简单工厂和工厂方法是直接做产品的,比如一条牛仔裤。这两种概念是不一样的,一定要清楚,因为他们之间的作用是完全不同的。

首先,先创建一个布料接口

/**
 * 这是一个布料接口
 */

public interface Cloth {
    void quality();
}

创建一个高端布料类并实现Cloth 接口

import android.util.Log;

/**
 * 这是高端布料
 */

public class HighEndCloth implements Cloth {
    @Override
    public void quality() {
        Log.d("TAG","高端布料质量好");
    }
}

创建一个低端布料类

import android.util.Log;

/**
 * 这是低端布料
 */

public class LowCloth implements Cloth {
    @Override
    public void quality() {
        Log.d("TAG","低端布料质量差");
    }
}

其次,创建一个拉链接口

/**
 * 这是一个拉链接口
 */

public interface Zipper {
    void durability();
}

创建一个高端拉链实体类,并实现Zipper 接口

import android.util.Log;

/**
 * 这是高端拉链
 */

public class HignEndZipper implements Zipper {
    @Override
    public void durability() {
        Log.d("TAG","高端拉链,很耐久!");
    }
}

创建一个低端拉链实体类,并实现Zipper 接口

import android.util.Log;

/**
 *这是低端拉链
 */

public class LowZipper implements Zipper {
    @Override
    public void durability() {
        Log.d("TAG","低端拉链,不耐久");
    }
}

再次,我们创建一个纽扣接口

/**
 * Created by Administrator on 2018/12/12.
 */

public interface PantsBuckle {
    void pantsBuckleMaterial();
}

创建一个高端纽扣实体类,并实现PantsBuckle 接口

import android.util.Log;

/**
 * 这是高端纽扣
 */

public class HighEndPantsBuckle implements PantsBuckle{
    @Override
    public void pantsBuckleMaterial() {
        Log.d("TAG","高端纽扣,镶钻的");
    }
}

创建一个低端纽扣实体类,并实现PantsBuckle 接口

import android.util.Log;

/**
 * 这是低端纽扣
 */

public class LowPantsBuckle implements PantsBuckle {
    @Override
    public void pantsBuckleMaterial() {
        Log.d("TAG","低端纽扣,铜质的");
    }
}

这下布料,纽扣,拉链都有了,最后我们就要创建工厂,我们现在需求主要是两种类型,一种是高端,一种是低端,所以建立两个工厂,一个高端工厂,专门做高端产品的,一个是低端工厂,专门做低端产品的,所以得先有一个工厂接口。
先创建一个牛仔裤工厂接口

/**
 *这是一个牛仔裤工厂接口,工厂主要生产布料,拉链以及纽扣
 */

public interface JeansFactory {
    Cloth createCloth();
    Zipper createZipper();
    PantsBuckle createPantsBuckle();
}

然后创建一个高端工厂,并实现JeansFactory接口


/**
 * 这是一个高端工厂
 */

public class HighEndFactory implements JeansFactory {
    @Override
    public Cloth createCloth() {
        return new HighEndCloth();
    }

    @Override
    public Zipper createZipper() {
        return new HighEndZipper();
    }

    @Override
    public PantsBuckle createPantsBuckle() {
        return new HighEndPantsBuckle();
    }
}

然后再创建一个低端工厂,并实现JeansFactory接口

/**
 * 这是一个低端工厂
 */

public class LowFactory implements JeansFactory {
    @Override
    public Cloth createCloth() {
        return new LowCloth();
    }

    @Override
    public Zipper createZipper() {
        return new LowZipper();
    }

    @Override
    public PantsBuckle createPantsBuckle() {
        return new LowPantsBuckle();
    }
}

现在产品族有了,工厂也有了,这时候调用者就可以找牛仔裤工厂(JeansFactory )定制自己所需要的产品了,比如高端的布料,低端的拉链和纽扣,可以这样调:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.hdc.test.abstractfactory.Cloth;
import com.hdc.test.abstractfactory.HighEndFactory;
import com.hdc.test.abstractfactory.JeansFactory;
import com.hdc.test.abstractfactory.LowFactory;
import com.hdc.test.abstractfactory.PantsBuckle;
import com.hdc.test.abstractfactory.Zipper;

/**
 *这是调用者
 */
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

//        //没有工厂的情况下调用
//        //调用JEE牛仔裤
//        Jeans jee = new JeansJee();
//        jee.wear();
//
//        //调用Levis牛仔裤
//        Jeans levis = new JeansLevis();
//        levis.wear();

        //简单工厂的情况下调用
        //调用JEE牛仔裤
//        Jeans jee = JeansFactory.jee();
//        jee.wear();
//
//        //调用Levis牛仔裤
//        Jeans levis = JeansFactory.levis();
//        levis.wear();

        //工厂方法情况下调用
        //调用JEE牛仔裤
//        Jeans jee = new JeeFactory().jeansBrandFactory();
//        jee.wear();
//
//        //调用Levis牛仔裤
//        Jeans levis = new LevisFactory().jeansBrandFactory();
//        levis.wear();
//
//        //调用新增品牌G-star牛仔裤
//        Jeans gstar = new GstarFactory().jeansBrandFactory();
//        gstar.wear();

        //抽象工厂情况下调用(牛仔裤工厂,我需要一条牛仔裤,这条牛仔裤必须是高端的布料,低端的拉链和低端的纽扣)
        //牛仔裤工厂使用高端工厂生产出高端布料
        JeansFactory jeansFactory_c = new HighEndFactory();
        Cloth cloth = jeansFactory_c.createCloth();
        cloth.quality();

        //牛仔裤工厂使用低端工厂生产出低端拉链
        JeansFactory jeansFactory_z = new LowFactory();
        Zipper zipper = jeansFactory_z.createZipper();
        zipper.durability();

        //牛仔裤工厂使用低端工厂生产出低端纽扣
        JeansFactory jeansFactory_p = new LowFactory();
        PantsBuckle pantsBuckle = jeansFactory_p.createPantsBuckle();
        pantsBuckle.pantsBuckleMaterial();
    }
}
23种设计模式之工厂模式_第3张图片
image.png

总结:
1.简单工厂(也称静态工厂):虽然不符合开闭原则,但实际应用最多的。
2.工厂方法:虽然符合了开闭原则,但会造成冗余,文件太多。
3.可以增加产品族,不可用增加产品。
谢谢大家查阅,有不对的地方欢迎指出,感恩。

你可能感兴趣的:(23种设计模式之工厂模式)