Java设计模式——工厂模式与抽象工厂模式

Hello大家晚上好,我是阿Q,好久不见,甚为想念(窃喜)。最近一段时间一直在参与安卓项目的开发(已忙成狗),也没能抽出时间来继续为大家总结设计模式的知识,在这里Say sorry了。由于好久没有写安卓方面的东西了,所以最近一段时间写起代码来事倍功半,踩了N多坑,被虐成Dog了。我最近有一个想法,就是想将之前学过的安卓知识再拾起来,以后在讲解java知识的同时也穿插着总结一下安卓的知识,也不知道大家感不感兴趣。如果大家想学习安卓或者有什么技术交流的可以在公众号后台给阿Q留言,阿Q视情况不定期更新安卓。好了,今晚回来的比较早,就抽时间讲一下工厂模式与抽象工厂设计模式吧。

简单工厂模式

首先呢,我们先来了解一下简单工厂模式。其实简单工厂模式并不是一个真正的设计模式,而是一种编程习惯。既然是一种习惯,就说明它有可取之处。所谓简单工厂模式,就是定义一个工厂类,将实例化对象的操作放在该工厂中去执行,当客户端调用的时候只需要将参数传入工厂就可得到该实体类。接下来阿Q就用一个小Demo来给大家做更详细的讲解。

一、定义一个抽象的接口

//定义课程接口
public interface Course {
    void desc();
}

二、声明实体类来实现该接口

//语文课类
public class Chinese implements Course{

    @Override
    public void desc() {
        System.out.println("这是语文课");
    }

}

//数学课类
public class Math implements Course{

    @Override
    public void desc() {
        System.out.println("这是数学课");
    }

}

//英语课类
public class English implements Course{

    @Override
    public void desc() {
        System.out.println("这是英语课");
    }

}

三、定义一个工厂类来管理上边声明的实体类

//定义工厂类
public class MyFactory {
    
    public static Course selectCourse(String type) {
        
        Course course = null;
        
        switch (type) {
            case "chinese":
                course = new Chinese();
                break;
    
            case "math":
                course = new Math();
                break;
                
            case "english":
                course = new English();
                break;
        }
        return course;
    }
}

四、客户端调用

public class TestDemo {
    
    public static void main(String[] args) {
        
        Course course1 = MyFactory.selectCourse("chinese");
        Course course2 = MyFactory.selectCourse("math");
        Course course3 = MyFactory.selectCourse("english");
        course1.desc();
        course2.desc();
        course3.desc();
    }

}

执行结果

1.png

简单设计模式的优点:对于客户端来说,去除了具体的类的依赖;无需提供具体的类名,只需要调用工厂类传入相应的参数就可以得到相应的实体类;

简单设计模式的缺点:就是每需要增加一个实体类,就需要去修改工厂类中的方法,可扩展性差;不同的产品需要不同额外参数的时候不支持;耦合性高,违反了开—闭原则。

工厂模式(Factory Pattern)

工厂模式是简单工厂的仅一步深化,在工厂模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂,也就是说每个对象都有一个与之对应的工厂。这样说有点抽象,那我们就用“实力”说话。

一、定义一个抽象接口

//课程接口
public interface Course {
    //课程描述
    void desc();
}

二、定义实体类实现抽象接口

//语文课实体类
public class Chinese implements Course{

    @Override
    public void desc() {
        System.out.println("这是语文课");
    }

}

//数学课实体类
public class Math implements Course{

    @Override
    public void desc() {
        System.out.println("这是数学课");
    }

}

三、定义工厂类

//定义工厂基类
public interface BaseFactory {
    Course getCourse();
}

四、定义各个实体类对应的工厂类

//语文课工厂类
public class ChineseFactory implements BaseFactory{

    @Override
    public Course getCourse() {
        return new Chinese();
    }

}
//数学课工厂类
public class MathFactory implements BaseFactory{

    @Override
    public Course getCourse() {
        return new Math();
    }

}

五、客户端调用

public class TestDemo {
    
    public static void main(String[] args) {
        
        try {
            //使用反射机制实例化工厂对象,因为字符串是可以通过变量改变的
            BaseFactory chineseFactory = (BaseFactory)Class.forName("com.itcast.ChineseFactory").newInstance();
            BaseFactory mathFactory=(BaseFactory)Class.forName("com.itcast.MathFactory").newInstance();
           
            //也可以用
            //BaseFactory chineseFactory = new ChineseFactory();
            //BaseFactory mathFactory = new MathFactory();
            Course chineseCourse = chineseFactory.getCourse();
            Course mathCourse = mathFactory.getCourse();
            chineseCourse.desc();
            mathCourse.desc();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
    }

}

执行结果:

2.png

工厂模式的优点:工厂方法把简单工厂的内部逻辑判断转移到了客户端代码来进行,克服了简单工厂模式违背的开—闭原则;保持了封装对象创建过程的优点;扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以;屏蔽产品的具体实现,调用者只关心产品的接口。

工厂模式的缺点:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。

抽象工厂模式(Abstract Factory Pattern)

抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。接下来同样举例说明。

一、定义实体类

//汽车座椅
public class Sofa {
    //颜色
    private String color;
    //舒适度
    private String soft;
    
    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public String getSoft() {
        return soft;
    }
    public void setSoft(String soft) {
        this.soft = soft;
    }
}

//汽车车轮
public class Wheel {
    //半径
    private String radiu;
    //大小
    private String size;
    
    public String getRadiu() {
        return radiu;
    }
    public void setRadiu(String radiu) {
        this.radiu = radiu;
    }
    public String getSize() {
        return size;
    }
    public void setSize(String size) {
        this.size = size;
    }

}

二、定义两个接口

//汽车座椅
public interface ISofa {
    //改变座椅颜色
    void changeColor();
    //改变座椅舒适度
    void changeSoft();
}

//汽车车轮
public interface IWheel {
    //改变大小
    void changeSize();
    //改变半径
    void changeRadius();
}

三、定义不同的实体类分别实现两接口

//本田汽车的座椅
public class BenSofa implements ISofa {

    @Override
    public void changeColor() {
        System.out.println("本田车变为蓝色了");
    }

    @Override
    public void changeSoft() {
        System.out.println("本田车变舒服了");
    }

}

//丰田汽车的座椅
public class FengSofa implements ISofa{

    @Override
    public void changeColor() {
        System.out.println("丰田车变为红色了");
    }

    @Override
    public void changeSoft() {
        System.out.println("丰田车变不舒服了");
    }

}

//本田汽车的车轮
public class BenWheel implements IWheel{

    @Override
    public void changeSize() {
        System.out.println("本田车轮子变大了");
    }

    @Override
    public void changeRadius() {
        System.out.println("本田车轮子半径变大了");
    }

}

//丰田汽车的车轮
public class FengWheel implements IWheel{
    
    @Override
    public void changeSize() {
        System.out.println("丰田车轮子变小了");
    }

    @Override
    public void changeRadius() {
        System.out.println("丰田车轮子半径变小了");
    }

}

四、定义抽象工厂类

//汽车工厂类
public interface CarFactory {
    //获取座椅对象
    ISofa getSofa();
    //获取车轮对象
    IWheel getWheel();
}

五、定义工厂实现类

//本田汽车
public class BenCarFactory implements CarFactory{

    @Override
    public ISofa getSofa() {
        return new BenSofa();
    }

    @Override
    public IWheel getWheel() {
        return new BenWheel();
    }
}

//丰田汽车
public class FengCarFactory implements CarFactory{

    @Override
    public ISofa getSofa() {
        return new FengSofa();
    }

    @Override
    public IWheel getWheel() {
        return new FengWheel();
    }

}

六、客户端调用

public class DemoTest {
    
    public static void main(String[] args) {
        CarFactory benCar = new BenCarFactory();
        ISofa sofa = benCar.getSofa();
        sofa.changeColor();
        sofa.changeSoft();
    }

}

执行结果:

3.png

抽象工厂模式优点: 抽象工厂模式最大的好处是易于交换产品系列,由于具体工厂类在一个应用中只需要在初始化的时候出现一次,这就使得改变一个应用的具体工厂变得非常容易,它只需要改变具体工厂即可使用不同的产品配置。不管是任何人的设计都无法去完全防止需求的更改,或者项目的维护,那么我们的理想便是让改动变得最小、最容易。抽象工厂模式的另一个好处就是它让具体的创建实例过程与客户端分离,客户端是通过它们的抽象接口操作实例,产品实现类的具体类名也被具体的工厂实现类分离,不会出现在客户端代码中。

抽象工厂模式缺点:客户端程序肯定不止一个,每次都需要声明,如果有100个调用CarFactory的类,就需要更改100次CarFactory benCar = new BenCarFactory();太繁琐。

好了今天就先说到这了,想了解更多学习知识,请关注微信公众号“阿Q说”,获取更多学习资料吧!你也可以后台留言说出你的疑惑,阿Q将会在后期的文章中为你解答。每天学习一点点,每天进步一点点。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容