工厂模式 订阅
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。 展开全文
工厂模式是我们最常用的实例化对象模式了,是用工厂方法代替new操作的一种模式。著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见。因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也是用来创建实例对象的,所以以后new时就要多个心眼,是否可以考虑使用工厂模式,虽然这样做,可能多做一些工作,但会给你系统带来更大的可扩展性和尽量少的修改量。
信息
本    质
工厂方法代替new操作
类    别
管理模式
俗    称
实例化对象模式
中文名
工厂模式
实    例
Jive论坛
外文名
Factory Method
工厂模式编程开发
工厂模式定义我们以类Sample为例, 如果我们要创建Sample的实例对象:Sample sample=new Sample();可是,实际情况是,通常我们都要在创建sample实例时做点初始化的工作,比如赋值 查询数据库等。首先,我们想到的是,可以使用Sample的构造函数,这样生成实例就写成:Sample sample=new Sample(参数);但是,如果创建sample实例时所做的初始化工作不是像赋值这样简单的事,可能是很长一段代码,如果也写入构造函数中,那你的代码很难看了(就需要Refactor重构)。为什么说代码很难看,初学者可能没有这种感觉,我们分析如下,初始化工作如果是很长一段代码,说明要做的工作很多,将很多工作装入一个方法中,相当于将很多鸡蛋放在一个篮子里,是很危险的,这也是有悖于Java面向对象的原则,面向对象的封装(Encapsulation)和分派(Delegation)告诉我们,尽量将长的代码分派“切割”成每段,将每段再“封装”起来(减少段和段之间耦合联系性),这样,就会将风险分散,以后如果需要修改,只要更改每段,不会再发生牵一动百的事情。在本例中,首先,我们需要将创建实例的工作与使用实例的工作分开, 也就是说,让创建实例所需要的大量初始化工作从Sample的构造函数中分离出去。这时我们就需要Factory工厂模式来生成对象了,不能再用上面简单new Sample(参数)。还有,如果Sample有个继承如MySample, 按照面向接口编程,我们需要将Sample抽象成一个接口.Sample是接口,有两个子类MySample 和HisSample .我们要实例化他们时,如下:ISample mysample=new MySample();ISample hissample=new HisSample();随着项目的深入,Sample可能还会"生出很多儿子出来", 那么我们要对这些儿子一个个实例化,更糟糕的是,可能还要对以前的代码进行修改:加入后来生出儿子的实例.这在传统程序中是无法避免的.但如果你一开始就有意识使用了工厂模式,这些麻烦就没有了.
收起全文
精华内容
下载资源
问答
  • 工厂模式

    千次阅读 2018-04-07 21:29:04
    一开始学工厂模式的时候一点也不明白,看了很多文章问了很多人为什么要使用工厂模式?为什么工厂模式就是解耦?看了几天有了点个人的理解,故写下来防止以后忘记。如果有什么不对或者理解不到位的地方,希望大神可以...

    一开始学工厂模式的时候一点也不明白,看了很多文章问了很多人为什么要使用工厂模式?为什么工厂模式就是解耦?看了几天有了点个人的理解,故写下来防止以后忘记。如果有什么不对或者理解不到位的地方,希望能告知。

    1.工厂模式的本质

    工厂模式又称为创建模式,它是建对象的一种最佳方式。工厂模式的本质就是用工厂方法代替new操作创建一种实例化对象的方式。一句话中总结就是方便创建 同种类型接口产品 的 复杂对象

    举例:实例化一个对象sample 一般会想到的方法是通过构造器来创建sample s=new sample();但是在实际情况下最好不要这样做,如果sample类的在实例化的时候需要初始化参数而这些参数需要别的类的信息,这样你new的话会增加你代码的耦合度,不利于维护。所以我们就需要将创建实例的工作和使用使用实例的工作分开,即:使用工厂方法创建实例的工作封装起来。这样我们在需要调用对象的时候就不需要关心那些复杂的实例化问题。
    接下来介绍具体有哪些工厂

    1.简单工厂模式(静态工厂模式)

    简单工厂模式中有抽象产品类:用来定义具体产品的共有属性,工厂类则负责生产具体产品。
    直接看代码:定义一个抽象产品类形状类Shape

    abstract class Shape(){
    public  abstract void shape();
    

    定义具体产品:

    class Circle extends Shape{
    	public void shape(){
    		System.out.println("圆形");
    	}
    }
    class Rectangle extends Shape{
    	public void shape(){
    		System.out.println("矩形");
    	}
    }
    class Triangle extends Shape{
    	public void shape(){
    		System.out.println("三角形");
    	}
    }
    

    定义一个工厂生产具体产品

    public class ShapeFactory{
    	public static Shape getshape(String sh){
    		if(sh.equals("圆形")){
    			return new Circle();
    		}else if(sh.equals("矩形")){
    			return new Rectangle();
    		}else if(sh.equals("三角形")){
    			return new Triangle();
    		}else {
    			return  null;
    		}
    	}
    	public static void main(String args[]){
    		ShapeFactory.getshape("圆形").shape();
    	}
    }
    output:圆形
    
    • 从简单工厂中我们可以看出使用一个静态方法将实例化的创建和使用分离开。我们只需要调用方法传递参数就可以获得我们需要的对象。
    • 缺点:我们不难看出如果我们想要增加一个形状类的产品不仅需要添加一个导出类而且我们必须要修改静态方法getshape,这样就违背了开闭原则(对于扩展是开放的,对于修改是封闭的)

    这时我们就可以想我们是不是可以将工厂也抽象出来?让具体工厂来负责创建具体产品对象,就上面的例子我们可以创建一个圆形的具体工厂让他只负责创建圆形产品对象,这样当我们想要增加一个产品的时候我们就只需要增加对应的工厂就行了,不需要修改其他东西。接下来我们说说工厂模式

    2.工厂模式

    就如上面所说的我们先了解工厂模式的具体概念:

    • 抽象工厂:工厂模式的核心,提供一个创建对象的接口,任何需要创建对象的具体工厂都要实现这个接口。
    • 具体工厂:实现抽象工厂接口的类,受到调用者的调用从而创建对象。
    • 抽象产品:工厂方法模式所创建的对象的超类。也就是所有具体产品的共同父类。
    • 具体产品:实现抽象工厂接口的类。工厂模式中所有创建的对象都是具体产品的实例。

    抽象产品Shape

    abstract class Shape {
    public  abstract void shape();
    }
    

    具体产品:

    class Circle extends Shape{
    	public void shape(){
    		System.out.println("圆形");
    	}
    }
    class Rectangle extends Shape{
    	public void shape(){
    		System.out.println("矩形");
    	}
    }
    class Triangle extends Shape{
    	public void shape(){
    		System.out.println("三角形");
    	}
    }
    

    抽象工厂:

    abstract class ShapeFactory{
    	public abstract Shape CreatShape();
    }
    

    具体工厂:

    class CircleFactory extends ShapeFactory{
    	public Shape CreatShape(){
    		return new Circle();
    	}
    }
    class RectangleFactory extends ShapeFactory{
    	public Shape CreatShape(){
    		return new Rectangle();
    	}
    }
    class TriangleFactory extends ShapeFactory{
    	public Shape CreatShape(){
    		return new Triangle();
    	}
    }
    

    测试:

    public class ShapeFactoryDemo{
    	public static void getshape(ShapeFactory sha){
    		sha.CreatShape().shape();
    	}
    	public static void main(String args[]){
    		getshape(new CircleFactory());
    	}
    }
    

    如上所示:即使我们增加一个新的形状类,我们也只需要增加相应的工厂类,不需要修改代码的任何方法。当我们需要这个新产品的时候我们只需要getshap(new 新的工厂类),其他的我们不用去关心,不需要了解方法的实现,对象是如何创建的,我们只需要调用方法就行了——良好的封装性。
    优点:

    1. 良好的封装性:如上面所说。
    2. 可以是代码结构变得清晰,有效的封装变化,通常new一个具体类是很复杂多变的,通过工厂方法将new的过程封装在具体工厂的方法中,调用者无须知道实例化的过程,只需要调用方法就可以得到自己想要的产品。

    有很多文章说工厂模式就是一种典型的解耦模式,对于这点我不是很清楚:抽象产品和抽象工厂之间是没有耦合问题,但是抽象工厂将耦合问题传给了具体工厂啊!具体工厂中的方法就是new出具体产品的实例,他们之间任然有耦合。这点我不是很明白,或许我的理解有问题。

    • 用到工厂模式的地方:

    1.创建对象的复杂度高。
    2.创建对象时需要增加依赖关系,就是说需要某些信息而这些信息不在复合类中。
    3.当系统需要比较好的延展性的时候。

    展开全文
  • 设计模式-JDK工厂模式

    万次阅读 2020-11-23 16:35:25
    五、JDK工厂模式 1、Collection中的iterator方法 2、Calendar创建实例 一、基本简介 工厂方法模式(Factory Method),定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法模式使一个类的实例化...

    目录

    一、基本简介

    二、优缺点

    1、优点

    2、缺点

    三、应用场景

    四、代码示例

    示例1:

    示例2:

    五、JDK工厂模式

    1、Collection中的iterator方法

    2、Calendar创建实例


    一、基本简介

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

    二、优缺点

    1、优点

    (1)良好的封装性、代码结构清晰。

    如一个调用者想创建一个对象,只需要知道其名称即可,降低了模板间的耦合。

    (2)扩展性好。

    如果想增加一个产品,只需扩展一个工厂类即可。

    (3)屏蔽产品类

    调用者只关心产品的接口。

    (4)典型的解耦框架

    2、缺点

    每增加一个产品,就需要增加一个产品工厂的类,增加了系统的复杂度。

    三、应用场景

    1、何时使用

    不同条件下创建不用实例时。方法是让子类实现工厂接口。

    2、使用场景

    • 创建对象需要大量重复的代码。
    • 创建对象需要访问某些信息,而这些信息不应该包含在复合类中。
    • 创建对象的生命周期必须集中管理,以保证在整个程序中具有一致的行为。

    3、应用实例

    (1) 需要一辆汽车,直接从工厂里面提货,不用去管这辆车是怎么做出来的。

    (2)hibernate换数据库只需换方言和驱动即可。

    (3)简单计算器的实现。

    四、代码示例

    示例1:

    1、Factory类

    public abstract class Factory {
        public abstract Product createProduct(String owner);
        public abstract void registerProduct(Product p);
        public abstract void getAllProductOwner();
        public Product create(String owner){
            Product p = createProduct(owner);
            registerProduct(p);
            return p;
        }
    }

     2、IDCardFactory类

    import java.util.ArrayList;
    import java.util.List;
    
    public class IDCardFactory extends Factory {
        List owners = new ArrayList();
        public Product createProduct(String owner){
            System.out.println("为 "+owner+" 创造产品成功...");
            return new IDCardProduct(owner);
        }
    
        @Override
        public void registerProduct(Product p) {
            String owner=((IDCardProduct)p).getOwner();
            owners.add(owner);
            System.out.println("注册 "+owner+" 的产品成功...");
        }
    
        @Override
        public void getAllProductOwner() {
            for(int i=0;i<owners.size();i++){
                System.out.println("产品用户:"+owners.get(i));
            }
        }
    }

    3、抽象类 

    public abstract class Product {
        public abstract void use();
    }

    4、 具体实现类

    public class IDCardProduct extends Product {
        String owner;
    
        public IDCardProduct(String owner) {
            this.owner = owner;
        }
    
        @Override
        public void use() {
            System.out.println("用户 "+owner+" 正在使用产品...");
        }
    
        public String getOwner() {
            return owner;
        }
    }

    5、测试类

    public class FactoryMain {
        public static void main(String[] args) {
            Factory f = new IDCardFactory();
            Product p = f.create("张三");
            p.use();
            System.out.println("--------------------");
            p = f.create("李四");
            p.use();
            System.out.println("--------------------");
            f.getAllProductOwner();
        }
    }

    6、控制台输出

    示例2:

    工厂接口:

    /**
     * 抽象工厂接口
     */
    public interface IWorkFactory {
        /**
         * 定义获取Work实例对象的方法
         * @return
         */
        Work getWork();
    }

    工厂具体实现:

    /**
     * IWorkFactory工厂的实现类
     *
     */
    public class StudentWorkFactory implements IWorkFactory {
    	@Override
        public Work getWork() {
            return new StudentWork();
        }
    }
    /**
     * IWorkFactory工厂的实现类
     */
    public class TeacherWorkFactory implements IWorkFactory {
    	@Override
        public Work getWork() {
            return new TeacherWork();
        }
    }

    product产品类:

    public interface Work {
        /**
         * 定义方法
         */
        void doWork();
    }

    产品生产类:

    /**
     *  Work接口的具体实现类
     *
     */
    public class TeacherWork implements Work {
        @Override
        public void doWork() {
            System.out.println("老师审批作业!");
        }
    }
    /**
     * Work接口的具体实现类
     */
    public class StudentWork implements Work {
    	   @Override
        public void doWork() {
            System.out.println("学生做作业!");
        }
    } 

    测试类:

    /**
     * 测试类
     *
     */
    public class FactoryTest {
        public static void main(String[] args) {
            IWorkFactory studentWorkFactory = new StudentWorkFactory();
            studentWorkFactory.getWork().doWork();
            IWorkFactory teacherWorkFactory = new TeacherWorkFactory();
            teacherWorkFactory.getWork().doWork();
        }
    }

     

    五、JDK工厂模式

    1、Collection中的iterator方法

    java.util.Collection接口中定义了一个抽象的iterator()方法,该方法就是一个工厂方法。

    对于iterator()方法来说Collection就是一个根抽象工厂,下面还有List等接口作为抽象工厂,再往下有ArrayList等具体工厂;

    java.util.Iterator接口是根抽象产品,下面有ListIterator等抽象产品,还有ArrayListIterator等作为具体产品;

    使用不同的具体工厂类中的iterator方法能得到不同的具体产品的实例;

    2、Calendar创建实例

    Calendar calendar = Calendar.getInstance();
    
    public static Calendar getInstance() {
        Locale aLocale = Locale.getDefault(Category.FORMAT);
        return createCalendar(defaultTimeZone(aLocale), aLocale);
    }
    private static Calendar createCalendar(TimeZone zone, Locale aLocale) {
        CalendarProvider provider = LocaleProviderAdapter.getAdapter(CalendarProvider.class, aLocale).getCalendarProvider();
        if (provider != null) {
            try {
                return provider.getInstance(zone, aLocale);
            } catch (IllegalArgumentException var7) {
            }
        }
    
        Calendar cal = null;
        if (aLocale.hasExtensions()) {
            String caltype = aLocale.getUnicodeLocaleType("ca");
            if (caltype != null) {
                byte var6 = -1;
                switch(caltype.hashCode()) {
                case -1581060683:
                    if (caltype.equals("buddhist")) {
                        var6 = 0;
                    }
                    break;
                case -752730191:
                    if (caltype.equals("japanese")) {
                        var6 = 1;
                    }
                    break;
                case 283776265:
                    if (caltype.equals("gregory")) {
                        var6 = 2;
                    }
                }
    
                switch(var6) {
                case 0:
                    cal = new BuddhistCalendar(zone, aLocale);
                    break;
                case 1:
                    cal = new JapaneseImperialCalendar(zone, aLocale);
                    break;
                case 2:
                    cal = new GregorianCalendar(zone, aLocale);
                }
            }
        }
    
        if (cal == null) {
            if (aLocale.getLanguage() == "th" && aLocale.getCountry() == "TH") {
                cal = new BuddhistCalendar(zone, aLocale);
            } else if (aLocale.getVariant() == "JP" && aLocale.getLanguage() == "ja" && aLocale.getCountry() == "JP") {
                cal = new JapaneseImperialCalendar(zone, aLocale);
            } else {
                cal = new GregorianCalendar(zone, aLocale);
            }
        }
    
        return (Calendar)cal;
    }

     

     

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 95,337
精华内容 38,134
关键字:

工厂模式