1. 聚能聊>
  2. 话题详情

聊聊设计模式,一个生产“对象”的地方,你有“对象”了吗?

前面我们聊了:
什么是设计模式?你知道多少?
你必须知道的六大设计原则
第一个设计模式,我是皇帝我独苗
今天我们来聊聊第二个设计模式,工厂方法模式。

除了使用new操作符之外,还有更多制造对象 的方法。实例化这个活动不应该总是公开地进行,初始化经常造成“耦合”问题。你是否想了解工厂模式如何从复杂的依赖中帮你脱困?
image
工厂模式属于创建型设计模式,需要生成的对象叫做产品 ,生成对象的地方叫做工厂 。工厂模式分为:工厂方法模式和抽象工厂模式,今天的主角是工厂方法模式。

描述
定义一个创建对象的工厂接口,让子类决定实例化哪一个类,将实际创建工作推迟到子类当中。此模式的核心精神是封装类中不变的部分,提取其中个性化善变的部分为独立类,通过依赖注入以达到解耦、复用和方便后期维护拓展的目的。它的核心结构有四个角色,分别是抽象工厂;具体工厂;抽象产品;具体产品。

使用场景
1、日志记录器:记录可能记录到本地硬盘、系统事件、远程服务器等,用户可以选择记录日志到什么地方。
2、数据库访问,当用户不知道最后系统采用哪一类数据库,以及数据库可能有变化时。
3、设计一个连接服务器的框架,需要三个协议,"POP3"、"IMAP"、"HTTP",可以把这三个作为产品类,共同实现一个接口。

优点
创建对象的接口,让子类决定具体实例化的对象,把简单的内部逻辑判断移到了客户端。扩展性高,想要增加一个产品,只要扩展一个工厂类就可以。

示例

public interface ShapeFactory {
    
    public Shape getShape();
    
}

public class CircleFactory implements ShapeFactory {  
  
    @Override  
    public Shape getShape() {  
        return new Circle();  
    }  
  
}  

public class RectangleFactory implements ShapeFactory {

    @Override
    public Shape getShape() {
        return new Rectangle();
    }

}

public class SquareFactory implements ShapeFactory {  
  
    @Override  
    public Shape getShape() {  
        return new Square();  
    }  
  
}  

public class ShapeFactory {  
      
    public Shape getShape(String type) {  
        if ("circle".equals(type)) {  
            return new Circle();  
        } else if ("rectangle".equals(type)) {  
            return new Rectangle();  
        } else if ("square".equals(type)) {  
            return new Square();  
        } else {  
            return null;  
        }  
    }  
      
}  

public class FactoryMethodDemo {  
      
    public static void main(String[] args) {  
        ShapeFactory circleFactory = new CircleFactory();  
        circleFactory.getShape().draw();  
        ShapeFactory rectangleFactory = new RectangleFactory();  
        rectangleFactory.getShape().draw();  
        ShapeFactory squareFactory = new SquareFactory();  
        squareFactory.getShape().draw();  
    }  
  
}  

最佳实践
工厂方法模式在项目中使用得非常频繁,以至于很多代码中都包含工厂方法模式。该模式几乎尽人皆知,但不是每个人都能用得好。熟能生巧,熟练掌握该模式,多思考工厂方法如何应用,而且工厂方法模式还可以与其他模式混合使用(例如模板方法模式、单例模式、原型模式等),变化出无穷的优秀设计,这也正是软件设计和开发的乐趣所在。

那么问题来了:
1、它还可以应用于哪些应用场景?

2、你做过的项目中采用工厂方法模式了吗?是否与其它模式混合使用?

3、你是否知道工厂方法模式的其它实现方式?(上代码)

4、说说你对工厂方法模式存在的疑问,或在使用工厂方法模式时遇到的那些坑。

参与话题

奖品区域 活动规则 已 结束

  • 奖品一

    阿里云代金券 x 5

  • 奖品二

    手机话费 x 1

  • 奖品三

    多功能工具箱 x 1

45个回答

1

cjsoldier 已获得多功能工具箱 复制链接去分享

这么好的问题怎么没人回答。首先感谢一下聊主,一天一个模式,不知不觉间就掌握了23种。

1、它还可以应用于哪些应用场景?
Java集合框架。List,Set都实现了Collection接口,都有iterator方法,这里就用到了工厂方法。
还有Java消息服务JMS的实现过程中也用到了。

2、你做过的项目中采用工厂方法模式了吗?是否与其它模式混合使用?
因为代码量比较少,我一般都用简单工厂模式了。简单工厂模式不属于GoF。
工厂方法还可以跟享元模式一起用。

3、你是否知道工厂方法模式的其它实现方式?(上代码)
真不知道还有什么其他的实现方式。只知道抽象工厂模式,跟工厂方法模式差不多,手机打字有点累啊。试一试吧。

interface FoodFactory{
    Noodles produceNoodles()
    Water produceWater()
}

class KangShiFuFactory implements FoodFactory{
    Noodles produceNoodles(){
        return new KangShiFuLaoTanSuanCai();
    }
    Water produceWater(){
        return new KangShiFuChunJingShui();
    }
}

4、说说你对工厂方法模式存在的疑问,或在使用工厂方法模式时遇到的那些坑。
工厂方法模式功能还是比较弱的。比如有一个食品工厂类,用这种模式只能生产一种食品。一个工厂不可能只生产一种食品的。
如果要生产100种食品,就需要新增200个类。
即便这个确实只生产一种食品,此时用工厂模式有点浪费,不如直接用简单工厂模式喽。

除非需要创建非常多的类,否则还是不要把问题复杂化了吧。

微wx笑 回复

手机打这么多,请收下我的膝盖

cjsoldier 回复
回复@微wx笑:

多谢打赏,因为我有好用的锤子便签啊:)

评论
1

sqtnbyy 已获得阿里云代金券 复制链接去分享

这许许多多的模式自然有用,可是这还不够。一天我看到了一句话,让我心头一惊感觉说的太好了。
这句话是这样的:“今天相比古代,有知识的人增加了,但是有智慧的,依然很少,希望你能够成为有智慧的人。”
怎么才能成为有智慧的人?我不知道我很困惑。
掌握再多的模式显然都还不够,都不足以让人拥有竞争优势,那怎么办呢?
... ...

微wx笑 回复

要知道聪明与智慧的区别,聪明知道怎么去获取,需要什么;而智慧知道的是什么是我不要的。懂得什么是我不要的,这才是真正的智慧;只有你知道什么是不要,你才能走的更远,走的更好,走的更久。你必须把最宝贵的注意力全部放在你自己身上,去点亮你的亮点。

评论
1

北方的郎 已获得阿里云代金券 复制链接去分享

1、它还可以应用于哪些应用场景?
工厂模式主要就是方便创建同种产品类型的复杂参数对象,工厂模式重点就是适用于 构建同产品类型(同一个接口 基类)的不同对象时,这些对象new很复杂,需要很多的参数,而这些参数中大部分都是固定的,所以程序员就可以用工厂模式封装。

2、你做过的项目中采用工厂方法模式了吗?是否与其它模式混合使用?
用过一些,主要是简单工厂模式。

3、你是否知道工厂方法模式的其它实现方式?(上代码)
public abstract class IFoods {

public abstract void desc();

}

public class LzFoods extends IFoods {

@Override
public void desc() {
    System.out.println("兰州拉面");
}

}

public class PaoFoods extends IFoods {

@Override
public void desc() {
    System.out.println("泡面");
}

}

public class HongShaoFoods extends IFoods {

@Override
public void desc() {
    System.out.println("红烧肉");
}

}

public class SimpleFoodsFactory {

public static final int TYPE_LZ = 1;
public static final int TYPE_PM = 2;
public static final int TYPE_HS = 3;

public static IFoods createFoods(int type) {
    switch (type) {
        case TYPE_LZ:
            return new LzFoods();
        case TYPE_PM:
            return new PaoFoods();
        case TYPE_HS:
        default:
            return new HongShaoFoods();
    }
}

}

4、说说你对工厂方法模式存在的疑问,或在使用工厂方法模式时遇到的那些坑。
感觉工厂方法模式还好,而用抽象工厂模式很容易搞出一堆类来,真的没有必要。

0

小不点02 已获得阿里云代金券 复制链接去分享

1、它还可以应用于哪些应用场景?
很多地方,只要需要new一个对象的地方都能用上啊!

2、你做过的项目中采用工厂方法模式了吗?是否与其它模式混合使用?
通常都是几种搭配使用的

3、你是否知道工厂方法模式的其它实现方式?(上代码)
不知道了

4、说说你对工厂方法模式存在的疑问,或在使用工厂方法模式时遇到的那些坑。
简单工厂、工厂方法模式、抽象工厂有点分不清。

0

海阔天空yy 已获得手机话费 复制链接去分享

1、它还可以应用于哪些应用场景?
在加解密里见过,指定一个加密算法,然后由工厂生生的类负责加密。

2、你做过的项目中采用工厂方法模式了吗?是否与其它模式混合使用?
我记得是RSA,和3DES加密用过,好像都是由同一个工厂生产出来的
其它模式更多的应该是原型化方法吧

3、你是否知道工厂方法模式的其它实现方式?(上代码)
interface Fruit {

//接口中的 public abstract 都是多余的声明,eclipse是发现不了的。  
//若是有心人就换编辑器,intellij idea,  
void eat();  

}

class Apple implements Fruit {

public void eat() {  
    System.out.println("Apple");  
}  

}

class Orange implements Fruit {

public void eat() {  
    System.out.println("Orange");  
}  

}

// 构造工厂类
// 也就是说以后如果我们在添加其他的实例的时候只需要修改工厂类就行了
class Factory {

public static Fruit getInstance(String fruitName) {  
    Fruit f = null;  
    if ("Apple".equals(fruitName)) {//这么写是为了避免null.equal(),空指针异常,有人会问这个为什么吗?    
        f = new Apple();  
    }  
    if ("Orange".equals(fruitName)) {  
        f = new Orange();  
    }  
    return f;  
}  

}

class Hello {

public static void main(String[] a) {  
    Fruit f = Factory.getInstance("Orange");  
    f.eat();  
}  

}
4、说说你对工厂方法模式存在的疑问,或在使用工厂方法模式时遇到的那些坑。
由于用的不算太多,所以也不好说。

0

小灬马 已获得阿里云代金券 复制链接去分享

24种设计模式,6种设计原则。我使用过的有单例模式,迭代器模式,建造者模式。这些模式的使用让代码编写不再枯燥,用到的多数是接口之间的回调,以及各种方法、类的封装,让使用变得简单。

0

shawn06 已获得阿里云代金券 复制链接去分享

问题一:
如果一个对象拥有很多子类,那么创建该对象的子类使用工厂模式可以面向接口的编程,为维护以及开发带来方便。
另外,如果创建某个对象时需要进行许多额外的操作,如查询数据库然后将查询到的值赋予要创建的对象,可以通过工厂模式进行成员变量的对象构造。

0

1012421978133772 复制链接去分享

纯新人,向大神门学习

微wx笑 回复

欢迎

评论
0

1565916681000154 复制链接去分享

第一次参与,学习学习

微wx笑 回复

加油

评论
0

1261321956657978 复制链接去分享

刚刚才进来,看看

微wx笑 回复

欢迎

评论
0

1211921954389321 复制链接去分享

你好我是这样的

微wx笑 回复

哦?

评论
0

1556521947688920 复制链接去分享

你好

微wx笑 回复

你好!

评论
0

1135821946013744 复制链接去分享

这个聊的什么,设计关键是要人性化,大众化,普及化

微wx笑 回复

欢迎大神科普

评论
0

1239220906584709 复制链接去分享

第一次注册阿里云。大神多多指教

微wx笑 回复

欢迎

评论
0

1239220906584709 复制链接去分享

第一次注册阿里云。大神多多指教

微wx笑 回复

欢迎

评论
0

netpop 复制链接去分享

我是土木工程专业的,跨专业像是进入了新世界。

微wx笑 回复

同专业也是隔行如隔山

评论
0

action1217 复制链接去分享

现在还没有,不知道怎么弄

微wx笑 回复

慢慢来

评论
0

1127221847025761 复制链接去分享

刚进来 感觉好强大

微wx笑 回复

欢迎

评论
0

小趣乐 复制链接去分享

厉害了

微wx笑 回复

←_←

评论
0

1590121819657341 复制链接去分享

刚刚注册,还没有了解清楚!

微wx笑 回复

欢迎,不懂就问

评论
3