工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 工厂模式于抽象工厂的区别 设计模式
工厂模式 工厂方法模式 抽象工厂模式 简单工厂模式 工厂模式于抽象工厂的区别 设计模式
工厂模式
定义一个用于创建对象的接口,让子类实现具体类的创建。工厂将类的实例化延迟的子类。
- 良好的分装性。对于具体产品,只要知道产品名称即可(类名或字符串),封闭了对产品创建的细节。
- 屏蔽具体产品类。通过抽象产品接口,屏蔽了各个具体产品的实现细节。使用者只关心产品接口就行。比如,java中JDBC的模式,可以很方便的从mysql切换到Oracle。
工厂方法模式,是典型的解耦框架。高层模块只需要知道产品的抽象类,符合迪米特法则。也符合依赖倒置原则,只依赖产品抽象类。也符合里氏替换原则,使用产品子类替换父产品,没有问题。
工厂方法模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8j7Q6e-1628926566)(imgs/factoryMethodOriginal.PG)]
上图就是工厂方法通用的类图,看起来还是比较简单的。
现在我们通过一个实际的案例来说明一下。我们模拟一下手机的制造过程。
按照通用类图,我们先创一个抽象的工程类: 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.forame(c.getame()).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() {println(华为手机打电话);}
}public class PhoneVivo implements Phone {@Overridepublic void call() {println(Vivo手机打电话);}
}public class PhoneXiaoMi implements Phone {@Overridepublic void call() {println(小米手机打电话);}
}
下面我们创建一个测试类,测试一下。
public class MethodOriginalMain {public static void main(String[] args) {FactoryPhoneAbstract factory = new FactoryBYD();Phone xiaoMi = ();();Phone vivo = ();();Phone huaWei = ();();}}
通过测试案例我们可以看到,在具体使用某个名牌手机时,
我们只需要告诉工厂手机品牌即可,不用关系具体的手机时怎么生产出来。
否则,我们就得自己一个去创建不同的手机对象,包括具体细节都得使用者自行处理。
这样耦合性太强,后期维护和扩展都会很麻烦。
我们现在把所有类的关系UML梳理一下,如下所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oqKmtWmk-1628926569)(imgs/factoryMethodOriginal2.PG)]
通过类图我们可以看出。通过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.forame(c.getame()).newInstance();} catch (Exception e) {e.printStackTrace();}return (T) human;}
}
这种改造就相当于是对工厂方法的一种简化改造。我们省去了抽象工作这一部分。
抽象工厂模式
我们还是先上一个抽象工厂的类图来看看。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-81adwFIC-16289265648)(imgs/factoryAbstract.PG)]
看上面的类图是不是感觉和工厂方法的类图区别不大。
现在将上面的案例稍微扩展一下。之前比亚迪的代工厂,只为各个品牌手机生产一种类型的手机。
现在如果每个品牌都生产两个版本的手机,一个是旗舰版,一个是青春版。
而且这两个版本的手机是有共性的,有关联的。下面我们就用抽象工厂实现一下这个场景。
创建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() {println(华为手机打电话);}
}public abstract class PhoneXiaoMiAbs implements Phone {@Overridepublic void call() {println(小米手机打电话);}
}public abstract class PhoneVivoAbs implements Phone {@Overridepublic void call() {println(Vivo手机打电话);}
}
现在各个品牌的抽象类都已构建,而且call方法都实现了。接着,我们创建真实的手机类。
public class HuaWeiFlagship extends PhoneHuaWeiAbs{@Overridepublic void photograph() {println(华为旗舰版手机,一亿像素。);}
}public class HuaWeiYouth extends PhoneHuaWeiAbs{@Overridepublic void photograph() {println(华为青春版手机,一百万像素);}
}public class VivoFlagship extends PhoneVivoAbs{@Overridepublic void photograph() {println(Vivo旗舰版,一亿像素);}
}public class VivoYouth extends PhoneVivoAbs{@Overridepublic void photograph() {println(Vivo青春版,一百万像素);}
}public class XiaoMiFlagship extends PhoneXiaoMiAbs{@Overridepublic void photograph() {println(小米旗舰版,一亿像素);}
}public class XiaoMiYouth extends PhoneXiaoMiAbs{@Overridepublic void photograph() {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();println(====================旗舰版手机产品线=====================);Phone huaWeiFlagship = ();();huaWeiFlagship.photograph();Phone xiaomiFlagship = ();();xiaomiFlagship.photograph();Phone vivoFlagship = ();();vivoFlagship.photograph();println(=====================青春版手机产品线=================);Phone huaWeiYouth = ();();huaWeiYouth.photograph();Phone xiaomiYouth = ();();xiaomiYouth.photograph();Phone vivoYouth = ();();vivoYouth.photograph();}}
Client端的演示案例就没有按照1:2的量来生产手机了,这里只做测试。
从工厂方法模式和抽象工厂模式的案例,我们可以看出它们的区别:
工厂方法模式针对的是一个产品等级结构;
而抽象工厂模式则是针对的多个相关产品等级结构。
#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
上一篇:单独编译和使用webrtc音频降噪模块(附完整源码+测试音频文件)
下一篇:【WebRTC】在Android上用NDK编译WebRtc音频增益模块(AGC),降噪(NS),java调用JNI实现功能
推荐阅读
留言与评论(共有 17 条评论) |
本站网友 刘孝英 | 26分钟前 发表 |
源站可能有防盗链机制 | |
本站网友 电脑上手机浏览器 | 11分钟前 发表 |
那么我们也就相当于要两个车间,来分别制造 | |
本站网友 大黑将志 | 5分钟前 发表 |
PhoneHuaWei | |
本站网友 深圳航空货运 | 16分钟前 发表 |
我们省去了抽象工作这一部分 | |
本站网友 dicks | 21分钟前 发表 |
);} }public class HuaWeiYouth extends PhoneHuaWeiAbs{@Overridepublic void photograph() {println(华为青春版手机,一百万像素);} }public class VivoFlagship extends PhoneVivoAbs{@Overridepublic void photograph() {println(Vivo旗舰版,一亿像素);} }public class VivoYouth extends PhoneVivoAbs{@Overridepublic void photograph() {println(Vivo青春版,一百万像素);} }public class XiaoMiFlagship extends PhoneXiaoMiAbs{@Overridepublic void photograph() {println(小米旗舰版,一亿像素);} }public class XiaoMiYouth extends PhoneXiaoMiAbs{@Overridepublic void photograph() {println(小米青春版,一百万像素);} } 我们创建了三个品牌的旗舰版 | |
本站网友 玉米须的药用价值 | 1秒前 发表 |
我们将上面的实现方式稍作变更即可 | |
本站网友 协同工作软件 | 7分钟前 发表 |
我们构建一个抽象的品牌手机类 | |
本站网友 脸上毛孔粗大 | 3分钟前 发表 |
工厂将类的实例化延迟的子类 | |
本站网友 牙痛怎么办 | 4分钟前 发表 |
建议将图片保存下来直接上传(img-8j7Q6e-1628926566)(imgs/factoryMethodOriginal.PG)] 上图就是工厂方法通用的类图,看起来还是比较简单的 | |
本站网友 阿弥陀佛故事 | 10分钟前 发表 |
那么接下来,就不直接构建真实的手机对象 | |
本站网友 wps2008 | 29分钟前 发表 |
public class PhoneHuaWei implements Phone {@Overridepublic void call() {println(华为手机打电话);} }public class PhoneVivo implements Phone {@Overridepublic void call() {println(Vivo手机打电话);} }public class PhoneXiaoMi implements Phone {@Overridepublic void call() {println(小米手机打电话);} } 下面我们创建一个测试类,测试一下 | |
本站网友 本是同根生相煎何太急 | 26分钟前 发表 |
从代码层面来,就相当于我们需要有两个工厂来生产各个品牌的两种手机 | |
本站网友 天方地圆 | 18分钟前 发表 |
按照通用类图,我们先创一个抽象的工程类: FactoryPhoneAbstract | |
本站网友 橘子的营养价值 | 4分钟前 发表 |
那么就相当于,在工厂方法中,只有一个车间为各个品牌代工制造手机 | |
本站网友 儿童健康网 | 10分钟前 发表 |
public class MethodOriginalMain {public static void main(String[] args) {FactoryPhoneAbstract factory = new FactoryBYD();Phone xiaoMi = ();();Phone vivo = ();();Phone huaWei = ();();}} 通过测试案例我们可以看到,在具体使用某个名牌手机时, 我们只需要告诉工厂手机品牌即可,不用关系具体的手机时怎么生产出来 | |
本站网友 血型遗传 | 25分钟前 发表 |
源站可能有防盗链机制 |