23种设计模式笔记第三篇简单工厂模式、工厂方法模式以及抽象工厂模式(参考狂神视频)

目录

工厂模式

简单工厂模式(静态工厂模式)Simple Factory

 工厂方法模式Factory Method

抽象工厂模式Abstract Factory

小结


工厂模式

作用:实现了创建者和调用者的分离,帮助我们实例化对象。

核心本质用工厂代替new操作实例化对象

                  将选择实现类,创建对象统一管理和控制,从而将调用者跟我们的实现类解耦

                  工厂模式是一种典型的解耦模式

满足的OOP七大原则:

                开闭原则

                依赖倒转原则

                迪米特法则(要权衡好)

分类:

        简单工厂模式:用来生成同一等级结构中的任意产品(对于增加的新的产品,需要扩展已有代码)。

        工厂方法模式:用来生成同一等级结构中的固定产品(支持增加任意产品)。

        抽象工厂模式:围绕一个超级工厂创建其他工厂。

适用场景作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过new就可以完成创建的对象,无需使用工厂模式。当需要系统有比较好的扩展性时,可以考虑工厂模式,不同的产品用不同的实现工厂来组装。

实际上,创建型模式(Creational Pattern)对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离

创建型模式在创建什么(What)由谁创建(Who)何时创建(When)等方面都为软件设计者提供了尽可能大的灵活性。

简单工厂模式(静态工厂模式)Simple Factory

就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。

简单工厂模式中的角色有:工厂,产品,客户端。看下例:

首先我们可以看一下类图

 具体实现代码如下:

创建一个Car接口

public interface Car {
	public void name();
}

编写两个实现类

public class WuLing implements Car{
	@Override
	public void name() {
		System.out.println("五菱宏光"); 
	}
}

public class Tesla implements Car{
	@Override
	public void name() {
		 System.out.println("特斯拉");
	}  
}

创建工厂类

public class CarFactory{
	public static Car getCar(String car) {
		if(car.equals("五菱")) {
			return new WuLing();
		}else if(car.equals("特斯拉")) {
			return new Tesla();
		}else {
			return null;
		}
	}
}

测试一下

public class Comsumer {
	public static void main(String[] args){
		Car car1 = CarFactory.getCar("五菱");
		Car car2 = CarFactory.getCar("特斯拉");
		car1.name();
		car2.name();
	}
}

输出的结果:

 

我无需再去关心车是怎么来的,我只需要提供一个名称,从工厂里面拿就行了。

我们能很清楚的感受到这个模式的弊端,如果我们现在想要新增一个Car接口的实现类,添加一个大众的车,就必须要去修改工厂中的getCar()方法,违背了开闭原则。

当然,我们可以修改工厂类中的方法,需要什么就获取什么,无需我们再去输入参数

public class CarFactory{
	public static Car getWuLing(){
        return new WuLing();
	}
    public static Car getTesla(){
        return new Tesla();
	}
}

其实这也是不满足我们的需求的,我们仍旧需要去修改代码,只是说不会像上一个方法要去代码逻辑中去修改。

简单工厂模式存在的问题:

                违背了开闭原则

                违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中

 工厂方法模式Factory Method

工厂方法模式是对简单工厂模式进一步的解耦,这相当于是把原本会因为业务代码而庞大的简单工厂类,拆分成了一个个的工厂类,这样代码就不会都耦合在同一个类里了。

工厂方法模式和简单工厂模式虽然都是通过工厂来创建对象,他们之间最大的不同是——工厂方法模式在设计上完全完全符合“开闭原则”。

直接看例子:

 具体代码实现如下:

Car接口、Tesla类和WuLing类不变

创建车工厂接口

public interface CarFactory{
    public Car getCar();
}

创建车工厂接口的实现类TeslaFactory工厂类和WuLingFactory类

public class TeslaFactory implements CarFactory{
    @Override
    public Car getCar(){
        return new Tesla();
    }
}

public class WuLingFactory implements CarFactory{
    @Override
    public Car getCar(){
        return new WuLing();
    }
}

最后测试一下

public class Comsumer {
	public static void main(String[] args){
		Car car1 = new WuLingFactory.getCar();
		Car car2 = new TeslaFactory.getCar();
		car1.name();
		car2.name();
	}
}

由于这里举的例子没有涉及到参数问题,所以我们的感觉不是很明显,试想一下,如果Tesla类或者WuLing类中有很多参数呢?这个方法对消费者来说就是友好的,我们无需去管车是怎么造的,它对应的工厂方法会去实例化它,我们只需要去调用工厂中的方法就可以了。

这里我认为狂神的流程图可能会更加清晰(加层)

以下情况下可以使用工厂方法模式:

        一个类不知道它所需要的对象的类。

        一个类通过其子类来指定创建哪个对象

优点:

        一个调用者想创建一个对象,只要知道其名称就可以了。

        扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。

        屏蔽产品的具体实现,调用者只关心产品的接口。

缺点:

        每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

抽象工厂模式Abstract Factory

抽象工厂模式相对工厂方法模式来讲,就是工厂方法模式是针对一个产品系列,而抽象工厂模式是针对多个产品系列的。

定义︰抽象工厂模式提供了一个创建一系列相关或者相互依赖对象的接口,无需指定它们具体的类。抽象工厂模式是工厂的工厂

我个人认为就是再加一层的意思,当然,这只是我个人的观点。

在讲案例之前,我们需要知道产品族和产品等级两个概念:

现在我们来看具体案例:

首先创建手机接口和路由器接口

//手机产品接口
public interface IPhoneProduct {
	void start();
	void shutdown();
	void callup();
	void sendSMS();
}
//路由器产品接口
public interface IRouterProduct {
	void start();
	void shutdown();
	void openWifi();
	void setting();
}

然后创建两个手机接口的实现类:小米手机和华为手机

//小米手机
public class XiaoMiPhone implements IPhoneProduct{

	@Override
	public void start() {
		System.out.println("开启小米手机");
	}

	@Override
	public void shutdown() {
		System.out.println("关闭小米手机");
	}

	@Override
	public void callup() {
		System.out.println("小米手机打电话");
		
	}

	@Override
	public void sendSMS() {
		System.out.println("小米手机发短信");
		
	}

}
//华为手机
public class HuaWeiPhone implements IPhoneProduct{

	@Override
	public void start() {
		System.out.println("开启华为手机");
	}

	@Override
	public void shutdown() {
		System.out.println("关闭华为手机");
	}

	@Override
	public void callup() {
		System.out.println("华为手机打电话");
		
	}

	@Override
	public void sendSMS() {
		System.out.println("华为手机发短信");
		
	}

}

创建两个路由器接口的实现类:小米路由器和华为路由器

//小米路由器
public class XiaoMiRouter implements IRouterProduct {

	@Override
	public void start() {
		System.out.println("启动小米路由器");
	}

	@Override
	public void shutdown() {
		System.out.println("关闭小米路由器");
		
	}

	@Override
	public void openWifi() {
		System.out.println("小米路由器打开WiFi");
	}

	@Override
	public void setting() {
		System.out.println("小米路由器设置");
	}

}
//华为路由器
public class HuaWeiRouter implements IRouterProduct {

	@Override
	public void start() {
		System.out.println("启动华为路由器");
	}

	@Override
	public void shutdown() {
		System.out.println("关闭华为路由器");
		
	}

	@Override
	public void openWifi() {
		System.out.println("华为路由器打开WiFi");
	}

	@Override
	public void setting() {
		System.out.println("华为路由器设置");
	}

}

编写一个抽象产品工厂来制造

//抽象产品工厂
public interface IProductFactory {	
	//生产手机
	IPhoneProduct iphoneProduct();
	//生产路由器
	IRouterProduct irouterProduct();
}

创建抽象产品工厂的实现类

//小米工厂
public class XiaoMiFactory implements IProductFactory {

	@Override
	public IPhoneProduct iphoneProduct() {
		return new XiaoMiPhone();
	}

	@Override
	public IRouterProduct irouterProduct() {
		return new XiaoMiRouter();
	}
}
//华为工厂
public class HuaWeiFactory implements IProductFactory {

	@Override
	public IPhoneProduct iphoneProduct() {
		return new HuaWeiPhone();
	}

	@Override
	public IRouterProduct irouterProduct() {
		return new HuaWeiRouter();
	}

}

编写客户端测试:

public class Client {
	public static void main(String[] args) {
		System.out.println("**********华为系列***********");
		//华为工厂
		HuaWeiFactory huaweiFactory = new HuaWeiFactory();
		IPhoneProduct huaweiPhone = huaweiFactory.iphoneProduct();
		huaweiPhone.start();
		huaweiPhone.callup();
	}
}

运行结果:

适用场景:客户端(应用层)不依赖于产品类实例如何被创建、实现等细节。强调一系列相关的产品对象(属于同一产品族)一起使用创建对象需要大量的重复代码提供一个产品类的库,所有的产品以同样的接口出现,从而使得客户端不依赖于具体的实现

优点:

        具体产品在应用层的代码隔离,无需关心创建的细节

        将一个系列的产品统一到一起创建

缺点:

        规定了所有可能被创建的产品集合,产品簇中扩展新的产品困难;

        增加了系统的抽象性和理解难度

小结

简单工厂模式:虽然某种程度上不符合设计原则,但实际使用最多

工厂方法模式:不修改已有类的前提下,通过增加新的工厂类实现扩展

抽象工厂模式:不可以增加产品,可以增加产品族

(戏言:没有什么是加一层解决不了的)

学到最后,我们必须要清楚的知道一点,就是不要本末倒置了,我们学习设计模式是为了更好的设计软件,不要为了使用某种设计模式而去设计

猜你喜欢

转载自blog.csdn.net/qq_44709970/article/details/124374065