1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 工厂模式于抽象工厂的区别 设计模式

工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 工厂模式于抽象工厂的区别 设计模式

时间:2022-06-06 02:50:26

相关推荐

工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 工厂模式于抽象工厂的区别 设计模式

工厂模式

定义一个用于创建对象的接口,让子类实现具体类的创建。工厂将类的实例化延迟的子类。

良好的分装性。对于具体产品,只要知道产品名称即可(类名或字符串),封闭了对产品创建的细节。屏蔽具体产品类。通过抽象产品接口,屏蔽了各个具体产品的实现细节。使用者只关心产品接口就行。比如,java中JDBC的模式,可以很方便的从mysql切换到Oracle。

工厂方法模式,是典型的解耦框架。高层模块只需要知道产品的抽象类,符合迪米特法则。也符合依赖倒置原则,只依赖产品抽象类。也符合里氏替换原则,使用产品子类替换父产品,没有问题。

工厂方法模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8gvj7Q6e-1623892635636)(imgs/factoryMethodOriginal.PNG)]

上图就是工厂方法通用的类图,看起来还是比较简单的。

现在我们通过一个实际的案例来说明一下。我们模拟一下手机的制造过程。

按照通用类图,我们先创一个抽象的工程类: FactoryPhoneAbstract。

public abstract class FactoryPhoneAbstract {public abstract <T extends Phone> T manufacturePhone(Class<T> c);}

抽象工厂的实现类,例如我们创建一个比亚迪工厂FactoryBYD,实现了抽象类的制造手机方法。这里我们通过反射的方式来实现。

当然这里的工厂创建的对象比较交单,真实的场景中,可能会比较复杂,步骤较多。所以更加有必要将对象的创建分装在工程里。

public class FactoryBYD extends FactoryPhoneAbstract {@Overridepublic <T extends Phone> T manufacturePhone(Class<T> c) {Phone phone = null;try {phone = (T) Class.forName(c.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) phone;}}

接下来我们创建产品Pone接口。这里我们只创建一个打电话的方法call()。

public interface Phone {void call();}

接着创建三个具体的手机类: PhoneVivo、PhoneHuaWei、PhoneXiaoMi。

public class PhoneHuaWei implements Phone {@Overridepublic void call() {System.out.println("华为手机打电话");}}public class PhoneVivo implements Phone {@Overridepublic void call() {System.out.println("Vivo手机打电话");}}public class PhoneXiaoMi implements Phone {@Overridepublic void call() {System.out.println("小米手机打电话");}}

下面我们创建一个测试类,测试一下。

public class MethodOriginalMain {public static void main(String[] args) {FactoryPhoneAbstract factory = new FactoryBYD();Phone xiaoMi = factory.manufacturePhone(PhoneXiaoMi.class);xiaoMi.call();Phone vivo = factory.manufacturePhone(PhoneVivo.class);vivo.call();Phone huaWei = factory.manufacturePhone(PhoneHuaWei.class);huaWei.call();}}

通过测试案例我们可以看到,在具体使用某个名牌手机时,

我们只需要告诉工厂手机品牌即可,不用关系具体的手机时怎么生产出来。

否则,我们就得自己一个去创建不同的手机对象,包括具体细节都得使用者自行处理。

这样耦合性太强,后期维护和扩展都会很麻烦。

我们现在把所有类的关系UML梳理一下,如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oqKmtWmk-1623892635639)(imgs/factoryMethodOriginal2.PNG)]

通过类图我们可以看出。通过FactoryBYD工厂实现类,

我们可以把创建三个不同手机对象的具体细节,都延迟到三个手机类的各自实现中去。

对于使用手机对象的用户来说,它只要关心Phone接口的打电话方法即可,

不用关系各品牌手机是怎么实现打电话的功能。

而且很容器在扩展一个新的手机品牌产品。

不需要去修改之前的已发布的代码。

简单工厂模式(静态工厂方法)

工厂方法有些变相的使用方式,例如简单工厂,也叫静态工厂方法。

我们将上面的实现方式稍作变更即可。

第一步,删除FactoryPhoneAbstract抽象类。

第二部,将FactoryBYD修改成如下代码所示。这里我们去掉FactoryBYD的继承类,

将manufacturePhone改成了静态方法

(这也是静态工厂方法名称的由来,当然不改成静态方法也是可以的)。

public class FactoryBYD {public static <T extends Phone> T manufacturePhone(Class<T> c) {Phone human = null;try {human = (T)Class.forName(c.getName()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) human;}}

这种改造就相当于是对工厂方法的一种简化改造。我们省去了抽象工作这一部分。

替代单例场景

延迟初始化

抽象工厂模式

我们还是先上一个抽象工厂的类图来看看。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-81adwFIC-1623892635648)(imgs/factoryAbstract.PNG)]

看上面的类图是不是感觉和工厂方法的类图区别不大。

现在将上面的案例稍微扩展一下。之前比亚迪的代工厂,只为各个品牌手机生产一种类型的手机。

现在如果每个品牌都生产两个版本的手机,一个是旗舰版,一个是青春版。

而且这两个版本的手机是有共性的,有关联的。下面我们就用抽象工厂实现一下这个场景。

创建FactoryPhoneInterface工厂接口,定义三个分别创建小米、华为、vivo三种手机品牌的方法。

相比较工厂方法,这里直接将工厂抽象成接口。当然工厂方法的抽象工厂也是可抽象成接口的。

这里主要的区别,是对不同品牌的手机各自定义了一个方法来完成对手机的构建。

public interface FactoryPhoneInterface {Phone manufactureXiaoMiPhone();Phone manufactureHuaWeiPhone();Phone manufactureVivoPhone();}

创建Phone接口,相比于之前的场景。这里增加了一个照相功能。

public interface Phone {// 大电话void call();// 照相void photograph();}

这里我们假设各个品牌手机打电话的功能都是一样的,只有照相的功能不同。

那么接下来,就不直接构建真实的手机对象。我们构建一个抽象的品牌手机类。

将各个品牌打电话的通用功能全部实现。代码如下:

public abstract class PhoneHuaWeiAbs implements Phone {@Overridepublic void call() {System.out.println("华为手机打电话");}}public abstract class PhoneXiaoMiAbs implements Phone {@Overridepublic void call() {System.out.println("小米手机打电话");}}public abstract class PhoneVivoAbs implements Phone {@Overridepublic void call() {System.out.println("Vivo手机打电话");}}

现在各个品牌的抽象类都已构建,而且call方法都实现了。接着,我们创建真实的手机类。

public class HuaWeiFlagship extends PhoneHuaWeiAbs{@Overridepublic void photograph() {System.out.println("华为旗舰版手机,一亿像素。");}}public class HuaWeiYouth extends PhoneHuaWeiAbs{@Overridepublic void photograph() {System.out.println("华为青春版手机,一百万像素");}}public class VivoFlagship extends PhoneVivoAbs{@Overridepublic void photograph() {System.out.println("Vivo旗舰版,一亿像素");}}public class VivoYouth extends PhoneVivoAbs{@Overridepublic void photograph() {System.out.println("Vivo青春版,一百万像素");}}public class XiaoMiFlagship extends PhoneXiaoMiAbs{@Overridepublic void photograph() {System.out.println("小米旗舰版,一亿像素");}}public class XiaoMiYouth extends PhoneXiaoMiAbs{@Overridepublic void photograph() {System.out.println("小米青春版,一百万像素");}}

我们创建了三个品牌的旗舰版、青春版手机,打电话的方法都继承各自品牌没有区别。

只是两个版本的手机像素各有差异。

那么我们怎么用工厂制造这些手机呢。

之前的比亚迪代工厂只需要制造各个品牌的同一种手机,现在不一样了需要两种了。

那么就相当于,在工厂方法中,只有一个车间为各个品牌代工制造手机。

现在,居然有两个类型了。那么我们也就相当于要两个车间,来分别制造。

从代码层面来,就相当于我们需要有两个工厂来生产各个品牌的两种手机。

public class FactoryBYDFlagship implements FactoryPhoneInterface {@Overridepublic Phone manufactureXiaoMiPhone() {return new XiaoMiFlagship();}@Overridepublic Phone manufactureHuaWeiPhone() {return new HuaWeiFlagship();}@Overridepublic Phone manufactureVivoPhone() {return new VivoFlagship();}}public class FactoryBYDYouth implements FactoryPhoneInterface {@Overridepublic Phone manufactureXiaoMiPhone() {return new XiaoMiYouth();}@Overridepublic Phone manufactureHuaWeiPhone() {return new HuaWeiYouth();}@Overridepublic Phone manufactureVivoPhone() {return new VivoYouth();}}

这样我们就拥有了两个工厂,分别生产旗舰版、青春版手机。

大家知道,一般旗舰版是高配价格贵销量相对较少,而青春版相对较多。

那么我们就可以通过Client端来协调,制造两台青春版手机,就制造一台旗舰版手机。

这样是为什么需要使用抽象工厂的原因,就是因为,同一产品族是有关联的。

public class FactoryAbsClient {public static void main(String[] args) {FactoryPhoneInterface factoryBYDFlagship = new FactoryBYDFlagship();FactoryPhoneInterface factoryBYDYouth = new FactoryBYDYouth();System.out.println("====================旗舰版手机产品线=====================");Phone huaWeiFlagship = factoryBYDFlagship.manufactureHuaWeiPhone();huaWeiFlagship.call();huaWeiFlagship.photograph();Phone xiaomiFlagship = factoryBYDFlagship.manufactureXiaoMiPhone();xiaomiFlagship.call();xiaomiFlagship.photograph();Phone vivoFlagship = factoryBYDFlagship.manufactureVivoPhone();vivoFlagship.call();vivoFlagship.photograph();System.out.println("=====================青春版手机产品线=================");Phone huaWeiYouth = factoryBYDYouth.manufactureHuaWeiPhone();huaWeiYouth.call();huaWeiYouth.photograph();Phone xiaomiYouth = factoryBYDYouth.manufactureXiaoMiPhone();xiaomiYouth.call();xiaomiYouth.photograph();Phone vivoYouth = factoryBYDYouth.manufactureVivoPhone();vivoYouth.call();vivoYouth.photograph();}}

Client端的演示案例就没有按照1:2的量来生产手机了,这里只做测试。

从工厂方法模式和抽象工厂模式的案例,我们可以看出它们的区别:

工厂方法模式针对的是一个产品等级结构;

而抽象工厂模式则是针对的多个相关产品等级结构。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。