记录自己对工厂模式的理解,如有不对的地方,请大家多多包涵,帮忙指出。
作用:实现了创建者和调用者的分离。
本文主要分三类:
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();
}
}
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();
}
}
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();
}
}
image.png
总结:
1.简单工厂(也称静态工厂):虽然不符合开闭原则,但实际应用最多的。
2.工厂方法:虽然符合了开闭原则,但会造成冗余,文件太多。
3.可以增加产品族,不可用增加产品。
谢谢大家查阅,有不对的地方欢迎指出,感恩。
网友评论