【深入浅出设计模式】三大工厂模式总结(最通俗易懂的讲解)

其他设计模式:
单例模式
代理模式
观察者模式

女娲造人的故事

相信这个故事大家都知道,简单来说就是女娲可以捏出不同样式的人。那么我们以这个故事为例,看看它是如何应用工厂模式的。

女娲可以类比为一个场景类Client捏出来的人可以理解为场景类中要获得的对象。那么如何获得对象呢?很简单,捏一个不就行了嘛!那么对应到代码中就是在Client中new了一个对象出来。但是这样会出现一个问题,如果女娲要捏一种类型的人还好,但是如果类型越来越多,比如现在有黑人、白人、黄人,那么不可避免的操作就会越来越繁琐,Client中的代码也会越来越冗余。女娲希望的是直接获取到对象,而省去中间那些繁杂的初始化过程。这时候就需要一个工具来帮助女娲了,八卦炉(工厂)。现在女娲想捏出哪种类型的人,只需要把泥巴丢进八卦炉里,然后八卦炉就会塑造出对应类型的人。这样,一个简单工厂就实现了。

一、简单工厂

1.类图

image-20220429103446209

2.解释

  • Human接口中包含了“人”的共同属性,皮肤颜色和语言,不同种类的人对接口进行不同实现即可。
public interface Human {
	//每个人种的皮肤都有相应的颜色
	public void getColor();
	//人类会说话
	public void talk();
}
  • HumanFactory创建工厂,当要获取不同人种的对象时,只需要把不同人种作为参数传给**createHuman()**方法即可。
public class HumanFactory {
public static <T extends Human> T createHuman(Class<T> c){
	//定义一个生产出的人种
	Human human=null;
	try {
	//产生一个人种
	human = (Human)Class.forName(c.getName()).newInstance();
	} catch (Exception e) {
	System.out.println("人种生成错误!");
	}
	return (T)human;
  }
}

  • createHuman()方法内部对传进来的参数进行判断,从而决定如何创建对象。
public class HumanFactory {
	public <T extends Human> T createHuman(Class<T> c){
	//定义一个生产的人种
	Human human=null;
	try {
		//产生一个人种
		human = (T)Class.forName(c.getName()).newInstance();
	} catch (Exception e) {
		System.out.println("人种生成错误!");
	}
	return (T)human;
  }
}

3.通用实现

  • 通用类图

image-20220427214747368

  • 抽象产品类Product
public interface Product {
}
  • 具体产品类ConcreteProduct
public class ConcreteProduct1 implements Product {
}

public class ConcreteProduct2 implements Product {
}

  • 场景类Client
public class Client {
    public static void main(String[] args) {
        SimpleFactory simpleFactory = new SimpleFactory();
        Product product = simpleFactory.createProduct(1);
        // do something with the product
    }
}
  • 工厂类SimpleFactory
public class SimpleFactory {
    public Product createProduct(int type) {
        if (type == 1) {
            return new ConcreteProduct1();
        } else if (type == 2) {
            return new ConcreteProduct2();
        }
        return new ConcreteProduct();
    }
}

但是在简单工厂中存在一个问题,当我们的对象类型,也就是人种类型增加时,我们就需要修改HumanFactory(工厂)中的逻辑代码,这就违反了开闭原则(只进行扩展,不进行修改)。为了解决这个问题,在简单工厂的基础上提出了工厂方法模式。

二、工厂方法

1.类图

​ 工厂方法就是在工厂的基础上加了一层抽象。用一个抽象类抽象出共同的创建对象的方法,具体的操作交给每一个工厂去执行。例如要增加一个Green Human类型人种,那么只需要创建一个GreenFactory类去继承AbstractHumanFactory类,然后实现其中的**createHuman()**抽象方法即可。这样就避免了修改而提高了扩展性。

image-20220429112535028

2.解释

  • AbstractHumanFactory
public abstract class AbstractHumanFactory {
    //通过定义泛型对createHuman的输入参数产生两层限制:
	//● 必须是Class类型;
	//● 必须是Human的实现类。
	public abstract <T extends Human> T createHuman(Class<T> c);
}

3.通用实现

  • 定义:定义一个用于创建对象的 接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。何为实例化延迟?一个对象被消费完毕后,并不立刻释放,工厂类 保持其初始状态,等待再次被使用,这样可以限制某一个产品类的最大实例化数量。

  • 通用类图

image-20220429113552305

  • 抽象产品类Product
public abstract class Product {
	//产品类的公共方法
	public void method1(){
	//业务逻辑处理
	}
	//抽象方法
	public abstract void method2();
}
  • 具体产品类ConcreteProduct
public class ConcreteProduct1 extends Product {
	public void method2() {
	//业务逻辑处理
	}
}
public class ConcreteProduct2 extends Product {
	public void method2() {
	//业务逻辑处理
	}
}
  • 抽象工厂类Creater
public abstract class Creator {
/*
* 创建一个产品对象,其输入参数类型可以自行设置
* 通常为String、Enum、Class等,当然也可以为空
*/
public abstract <T extends Product> T createProduct(Class<T> c);
}

  • 具体工厂类ConcreteCreator
public class ConcreteCreator extends Creator {
public <T extends Product> T createProduct(Class<T> c){
	Product product=null;
	try {
	product = (Product)Class.forName(c.getName()).newInstance();
	} catch (Exception e) {
	//异常处理
	}
	return (T)product;
  }
}

  • 场景类Client
public class Client {
	public static void main(String[] args) {
		Creator creator = new ConcreteCreator();
		Product product = creator.createProduct(ConcreteProduct1.class);
		/*
		* 继续业务处理
		*/
	}
}

既然是人,那肯定就应该分男女啊,并且应该同时出现(注意)。但是我们上述的操作并不能创建出男性人种和女性人种,那如何进行修改呢?可以用到抽象工厂模式

三、抽象工厂

1.类图

image-20220429115515128

对比一下看看有哪些改变

  • 不同的人种类型(对象类型)抽象为了一个个的抽象类,然后再创建该人种类型男性类女性类继承该人种类型的抽象类。抽象类中是没有实现性别这个方法的,它交给具体的男性类女性类实现

  • 原本的抽象工厂类变成了工厂接口,接口中包含创建不同**人种类型(对象类型)**的方法,创建女性工厂类和男性工厂类实现该接口。(注意:对一个人种类型(对象类型)进行实例化时,女性工厂类和男性工厂类一定是同时实例化的,不过我们可以调整让他们创建出对象的比例不同,例如创建1个女性对象就要创建1.5个男性对象。)

2.解释

  • 人种接口Human
public interface Human {
	//每个人种都有相应的颜色
	public void getColor();
	//人类会说话
	public void talk();
	//每个人都有性别
	public void getSex();
}
  • 抽象人种类AbstractHuman
public abstract class AbstractWhiteHuman implements Human {
	//白色人种的皮肤颜色是白色的
	public void getColor(){
		System.out.println("白色人种的皮肤颜色是白色的!");
	}
	//白色人种讲话
	public void talk() {
		System.out.println("白色人种会说话。");
	}
}

  • 具体人种性别实现类Female/Male Human
public class FemaleWhiteHuman extends AbstractWhiteHuman {
	//白人女性
	public void getSex() {
		System.out.println("白人女性");
	}
}

  • 工厂接口 HumanFactory
public interface HumanFactory {
	//制造一个黄色人种
	public Human createYellowHuman();
	//制造一个白色人种
	public Human createWhiteHuman();
	//制造一个黑色人种
	public Human createBlackHuman();
}

  • 具体性别工厂实现类Female/Male Factory
public class FemaleFactory implements HumanFactory {
	//生产出黑人女性
	public Human createBlackHuman() {
		return new FemaleBlackHuman();
	}
	//生产出白人女性
	public Human createWhiteHuman() {
		return new FemaleWhiteHuman();
	}
	//生产出黄人女性
	public Human createYellowHuman() {
		return new FemaleYellowHuman();
	}
}

3.通用实现

  • 定义:抽象工厂模式创建的是对象家族,也就是很多对象而不是一个对象,并且这些对象是相关的,也就是说必须一起创建出来(男性和女性)。而工厂方法模式只是用于创建一个对象,这和抽象工厂模式有很大不同。

  • 通用类图

image-20220429121553102

  • 抽象产品类 AbstractProductA
public abstract class AbstractProductA {
	//每个产品共有的方法
	public void shareMethod(){
	}
	//每个产品相同方法,不同实现
	public abstract void doSomething();
}

  • 具体产品实现类ProductA1
public class ProductA1 extends AbstractProductA {
	public void doSomething() {
		System.out.println("产品A1的实现方法");
	}
}
  • 抽象工厂类AbstractCreator
public abstract class AbstractCreator {
//创建A产品家族
public abstract AbstractProductA createProductA();
//创建B产品家族
public abstract AbstractProductB createProductB();
}

  • 具体工厂实现类Creator
public class Creator1 extends AbstractCreator {
	//只生产产品等级为1的A产品
	public AbstractProductA createProductA() {
		return new ProductA1();
	}
	//只生产产品等级为1的B产品
	public AbstractProductB createProductB() {
		return new ProductB1();
	}
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值