淡水鱼养殖场就是一个简单工厂java_哇塞!这么全的工厂模式你见过吗

设计模式二--工厂模式

举例:

女娲采集黄土捏成人的形状,然后放到八卦炉中烧制,然后放到土地上生长,但是意外随时都会发生。

第一次烤人,感觉应该熟了,往地上一放,哇,没烤熟,白人诞生了。

第二次烤人,上一次没有烤熟,这次多烤一会,放到世间一看,哇,熟过头了,于是黑人诞生了。

第三次烤人,一边烧制一遍看,知道表皮发黄,嘿,刚刚好,于是黄种人诞生了。

思考:

在面向对象编程的思想中,万物皆对象。于是我们抽象出具体的三个对象。

女娲,八卦炉,三种不同肤色的人。

女娲可以用场景类Client来表示,八卦炉可以用工厂来表示,三个不同肤色的人,他们都是同一个接口下面的不同实现类。

于是我们生成类图。

4cabbee95b6521931461f0f3306d4fb6.png

AbstarctHummanFactory是一个抽象类,HumanFactoruy是一个实现类,完成具体的任务,创建人类。Human是人类- 总称,三个人种是其实现类,Nawa是一个场景,负责模拟这个场景,发起任务。

人类接口

/**

* @atuhor sha1024

*/

public interface Human {

void getTalk();

void getColor();

}

复制代码

白人人类

/**

* @atuhor sha1024

*/

public class WhiteHuman implements Human{

@Override

public void getTalk() {

System.out.println("我是一个白人");

}

@Override

public void getColor() {

System.out.println("我的皮肤是白色的");

}

}

复制代码

黄色人种

/**

* @atuhor sha1024

*/

public class YellowHuman implements Human{

@Override

public void getTalk() {

System.out.println("黄种人说话最好听");

}

@Override

public void getColor() {

System.out.println("我的皮肤是黄色的");

}

}

复制代码

黑色人种

/**

* @atuhor sha1024

*/

public class BlackHuman implements Human{

@Override

public void getTalk() {

System.out.println("黑人说话听不懂");

}

@Override

public void getColor() {

System.out.println("我的皮肤是黑色的");

}

}

复制代码

定义一个抽象工厂,定义了一个泛型实现了Human

/**

* @atuhor sha1024

*/

public abstract class AbstarctHummanFactory {

public abstract T createHuman(Class c);

}

定义了一个人类工厂实现抽象人类工厂

public class HummanFactory extends AbstarctHummanFactory {

@Override

public T createHuman(Class c) {

//定义一个人种

Human human = null;

try{

human = (T)Class.forName(c.getName()).newInstance();

}catch (Exception e){

throw new RuntimeException("定义人种错误");

}

return (T)human;

}

}

复制代码

女娲类,实现具体的场景

public static void main(String[] args) {

AbstarctHummanFactory hummanFactory = new HummanFactory();

Human whiteHuman = hummanFactory.createHuman(WhiteHuman.class);

whiteHuman.getColor();

whiteHuman.getTalk();

Human blackHuman = hummanFactory.createHuman(BlackHuman.class);

blackHuman.getTalk();

blackHuman.getColor();

Human yellowHuman = hummanFactory.createHuman(YellowHuman.class);

yellowHuman.getColor();

yellowHuman.getTalk();

SpringApplication.run(FactoryApplication.class, args);

}

复制代码

执行结果2cbadd84bfce07f5e1006768414e35e6.png

工厂方法模式的定义

定义一个用于创建对象的接口,让子类来决定实例化哪一个。工厂方法使一个类的实例化延迟到其子类。

db4c9dff0f1b6940749d8659a213364e.png

在工厂模式中,抽象产品类Product负责定义产品的共性,实现对事物最抽象的定义;Creator为抽象创建类,也就是抽象工厂,具体如何创建产品类是由具体的实现工厂ConcreateCreator完成的。

具体的产品类可以有多个,都继承抽象产品类

/**

* 抽象产品类

* @atuhor sha1024

*/

public abstract class Product {

//产品类的公共方法

public void method1(){

System.out.println("我是抽象工厂方法1");

}

/**

* 抽象方法

*/

public abstract void method2();

}

复制代码

产品类1

/**

* @atuhor sha1024

*/

public class ConcreateProduct1 extends Product {

@Override

public void method2() {

/**

* 具体业务逻辑

*/

}

}

复制代码

产品类2

/**

* @atuhor sha1024

*/

public class ConcreateProduct2 extends Product {

@Override

public void method2() {

/**

* 业务逻辑

*/

}

}

复制代码

抽象工厂

/**

* @atuhor sha1024

*/

public abstract class Creator {

/**

* 创建一个产品对象,其输入任何参数类型都可以自行设置

* 通常为String,Enum,Class,也可以为空

*/

public abstract T createProduct(Class c);

}

复制代码

具体如何产生一个产品对 对象是由具体的工厂实现类来决定的

/**

* 通过发射获取到实例

* @atuhor sha1024

*/

public class ConcreateCreator extends Creator{

@Override

public T createProduct(Class c) {

Product product = null;

try{

product = (T)Class.forName(c.getName()).newInstance();

}catch (Exception e){

throw new RuntimeException(e.getMessage());

}

return (T)product;

}

}

复制代码

场景类

/**

* @atuhor sha1024

*/

public class Client {

public static void main(String[] args){

Creator creator = new ConcreateCreator();

Product product = creator.createProduct(ConcreateProduct1.class);

/**

* 业务逻辑

*/

product.method2();

}

}

复制代码

工厂模式的优点:

良好的封装性,代码结果清晰。

工厂方法模式的扩展性非常好。

屏蔽产品类,产品类如何变化,调用者不用关心,它只需要关心产品的接口。更好的实现了解耦合。

工厂方法模式使用场景

工厂方法是new一个对象的 替代品,所以在所有需要生成对象的地方都可以使用,但是要考虑是否要增加一个产品类来增加代码的复杂性。

需要灵活的可扩展的框架时,可以考虑采用工厂方法模式。

工厂模式的扩展

缩小为简单工厂模式

f55c2f36096f81e5c0be8d0139d98429.png

上图中我们去掉了AbstarctHummanFactory

抽象人类工厂,同时把createHuman改为静态类型。

/**

* @atuhor sha1024

*/

public class NvWa {

public static void main(String[] args){

Human human = HummanFactory2.createHuman(YellowHuman.class);

Human human2 = HummanFactory2.createHuman(BlackHuman.class);

}

}

复制代码

运行结果没用发生变化,但是我们的类图变得更加简单了,因为简单所以我们称为简单工厂模式

升级为多个工厂模式

bac662fef57bf61c67f6ac3dcc4834db.png

当我们在做一个复杂项目的时候,经常会遇到初始化一个对象很费力的情况,所有产品都放到一个工厂方法中进行初始化会使代吗结构不清晰。例如:一个产品类有5个具体实现类,每个实现类的初始化方法都不相同,如果写在工厂中,会导致该方法巨大无比。

考虑到要结构清晰,我们就为每个产品定义一个创造者,然后由调用者去选择与哪个工厂方法关联。

定义一个抽象工厂

public abstract class AbstarctHummanFactory {

public abstract Human createHuman();

}

复制代码

黑人人种创建工厂

public class BlackHummanFactory extends AbstarctHummanFactory {

@Override

public Human createHuman() {

return new BlackHuman();

}

}

复制代码

黄色人种创建工厂

public class YellowHummanFactory extends AbstarctHummanFactory {

@Override

public Human createHuman() {

return new YellowHuman();

}

}

复制代码

场景类

public static void main(String[] args){

Human yellowHuman = (new YellowHummanFactory()).createHuman();

yellowHuman.getTalk();

yellowHuman.getColor();

Human blackHuman = (new BlackHummanFactory()).createHuman();

blackHuman.getTalk();

blackHuman.getColor();

}

复制代码

运行结果还是相同的,每一个产品类都对应了一个创建类好处就是创建类职责清晰,而且结构简单,但是给可扩展性和维护性带来了一定的影响。

当然,在复杂的应用场景中一般采用多工厂模式,然后增加一个协调类,避免调用者和各个子工厂交流,对高层模块提供统一调用api。

替代单例模式

0c6662cd2d122715bd00f8289f99da44.png

Singleton定义了一个private 的无参构造函数,目的是不允许通过new 的方式创建一个对象

public class Singleton {

private Singleton(){}

public void doSomeThing(){

//业务逻辑

}

}

复制代码

单例类,Singleton保证不能通过正常情况下建立一个对象,只能通过反射方式创建

public class SingletonFactory {

private static Singleton singleton;

static {

try{

Class c1 = Class.forName(Singleton.class.getName());

//获取无参构造函数

Constructor constructor = c1.getDeclaredConstructor();

//设置无参是可访问的

constructor.setAccessible(true);

//产生一个实例对象

singleton = (Singleton) constructor.newInstance();

}catch(Exception e){

}

}

public static Singleton getSingleton(){

return singleton;

}

复制代码

通过获得类构造器,然后设置访问权限,生成一个对象,然后提供外部访问,保证内部中的对象唯一。当然,其他的类也能通过反射的方式获得一个单例对象。

延迟初始化

fd45080159aecb7bf405e0cccd69f5d7.png

ProductFactory负责产品类对象的创建,并通过prMap创建一个缓存,对需要被重用的对象保留

public class ProductFactory {

private static final Map prMap = new HashMap<>();

public static synchronized Product createProduct(String type) throws Exception{

Product product = null;

//判断缓存中是否有这个对象

if(prMap.containsKey(type)){

product = prMap.get(type);

}else{

if(type.equals("Product1")){

product = new ConcreateProduct1();

}else{

product = new ConcreateProduct2();

}

//同时缓存数据到prMap中

prMap.put(type,product);

}

return product;

}

}

复制代码

通过定义一个Map容器,容纳所有对象,如果Map容器中已经有的对象,则直接取出;如果没用,则根据需要的类型产生一个对象并放入到Map容器中。

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[哇塞!这么全的工厂模式你见过吗]http://www.zyiz.net/tech/detail-142044.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值