简单工厂、工厂模式初学习

171 阅读5分钟

借鉴 :《大话数据结构》 http://www.cnblogs.com/cj723/

活字印刷--面向对象

活字印刷,即当需要改变部分字的时候,不需要整个刻板全部重新刻,解耦。

  • 可维护
    • 要改,只需更改要改之字
  • 可复用
    • 这些字并非这次用完就无用,完全可以后来的印刷中重复使用
  • 可扩展
    • 若需要在已有内容里加字,只需要另刻字加入即可
  • 灵活性好
    • 子的排版可能是竖排也可能是横排,需求改变时只需要将活字移动就克做到满足排列需求

所以需要通过 封装、继承、多态把程序的耦合度降到最低

  • 业务的封装
    • 将业务逻辑与界面逻辑分开,让他们之间的耦合度下降
    • 比如一个Windows计算器,将计算和显示分开
      • Operation运算类
        • 加减乘除功能具体实现
      • 客户端类
        • 输入界面的UI
    • 只增加一个功能,不影响计算器原有的功能代码发生改变--将加减乘除等运算分离,修改其中一个不影响另外的几个
      • Operation类
        • set 与 get 方法
        • 虚方法:GetResult()用于得到结果
      • 加减乘除类 继承 Operation类
        • 加减乘除功能具体实现
          • 对于每一个功能重写GetResult()方法
      • 客户端类

现在的问题是:如何去实例话一个对象

1.简单工厂模式--"switch-case"--类创建型模式

专门定义一个类用来负责创建其他类的实例,被创建的实例通常都具有共同的父类

public class OperationFactory {
      public static BaseOperation createOperation(String operate) {
      		  int sum = 0;
            switch (operate) {
                  case "+":
                  		 sum=new OperationAdd();
                        break;
                  case "-":
                  		 sum=new OperationSub();
                        break;
                  case "*":
                  		 sum=new OperationMul();
                        break;
                  case "/":
                  		 sum=new OperationDiv();
                        break;      
            }
            return sum ;
      }
}
  • 优点
    • 工厂类是整个模式的关键,包含了必要的逻辑判断,根据外界给定的信息,决定究竟应该创建哪个具体类的对象
  • 缺点
    • 由于工厂类集中了所有实例的创建逻辑,违反了高内聚责任分配原则,将全部创建逻辑集中到了一个工厂类中;它所能创建的类只能是事先考虑到的,如果需要添加新的类,则就需要改变工厂类了。
  • 意义
    • 通过使用工厂类,外界可以从直接创建具体产品对象转换为直接使用对象就可以了,而不必管这些对象是如何创建及如何组织的,明确了各自的职责和权利,有利于整个软件体系结构的优化

相关借鉴: https://www.jianshu.com/p/3f824a91d73b https://juejin.cn/post/6844903501240205320

继续阅读的知识点补充与温故:

1.抽象--abstract

Animal类根本就不可能实例化,一只猫长什么样子可以想象,但是实例化一个动物,那么动物长什么样?所以动物是一个抽象的名词,没有具体对象与之对应

【抽象类的注意事项】

  • 抽象类不能实例化
    • Animal实例化没有意义
  • 抽象方法是 必须 被子类重写 的方法
  • 如果类中包含抽象方法,那么累就必须定义为抽象类,不论是否还包含其他一般的方法

抽象类应该拥有尽可能多的共同代码,拥有尽可能少的数据

设计一个抽象类时,一定是用来继承的

如果牛、羊、狗、猫、猴是最后一级,那么他们就是具体类,
但如果还有更下面一级的金丝猴继承于猴,哈巴狗继承于狗,
那就需要考虑把猫和狗改为抽象类的了

2.开放-封闭原则--多扩展,少修改--面对对象设计的核心所在

精髓:面对需求,对程序的改动是通过增加新代码进行的,而不是更改现有的代码

  • 对于拓展是开放的
  • 对于更改是封闭的

2.工厂模式

定义一个用于创建对象的接口,让子类决定实例化哪一个类

工厂模式使一个类的实例化延迟到其子类

简单工厂模式 和 工厂模式 的 对比例子--雷锋工厂

//定义一个雷锋类
public class LeiFeng {

    public void sweep(){
        System.out.println("扫地");
    }

    public void wash(){
        System.out.println("洗衣");
    }

    public void cook(){
        System.out.println("做饭");
    }
}
//学雷锋的大学生类,继承雷锋  
public class Undergraduate extends LeiFeng  
{  
  
}
//客户端代码  
public class Main  
{  
    public static void main(String[] args)  
    {  
        LeiFeng xueleifeng = new Undergraduate(); 
        xueleifeng.buyRice(); 
        xueleifeng.sweep();  
        xueleifeng.wash();  
    }  
}  
  • 现在假设有三个人要去代替他做这些事,那就应该实例化三个学雷锋的大学生对象了
LeiFeng student1 = new Undergraduate();  
student1.buyRice();  
  
LeiFeng student2 = new Undergraduate();  
student2.sweep();  
  
LeiFeng student3 = new Undergraduate();  
student3.wash();  
  • 然而不仅仅有大学生去帮助老人,还有“社区志愿者”也会参与其中,那么这样的写法就非常不合适了,因为我们需要更改多个实例化的地方,所以还需要增加一个继承“雷锋”的类 --“社区志愿者”类

1.简单工厂模式

//社区志愿者  
public class Volunteer extends LeiFeng  
{  
  
}  
//简单工厂类  
public class SimpleFactory  
{  
    public static LeiFeng createLeiFeng(String type)  
    {  
        LeiFeng result = null;  
  
        if ("学雷锋的大学生".equals(type))  
        {  
            result = new Undergraduate();  
        }  
        else if ("社区志愿者".equals(type))  
        {  
            result = new Volunteer();  
        }  
  
        return result;  
    }  
}  

//客户端代码,如果要换,就只需要换“学雷锋的大学生”为“社区志愿者” 
 
LeiFeng studentA = SimpleFactory.createLeiFeng("学雷锋的大学生");  
studentA.buyRice();  
  
LeiFeng studentB = SimpleFactory.createLeiFeng("学雷锋的大学生");  
studentB.sweep();  
          
LeiFeng studentC = SimpleFactory.createLeiFeng("学雷锋的大学生");  
studentC.wash();  

2.工厂模式

//雷锋工厂  
public interface IFactory  
{  
    LeiFeng createLeiFeng();  
}  
//学雷锋的大学生工厂  
public class UndergraduateFactory implements IFactory  
{  
    public LeiFeng createLeiFeng()  
    {  
        return new Undergraduate();  
    }  
}  
//社区志愿者工厂  
public class VolunteerFactory implements IFactory  
{  
    public LeiFeng createLeiFeng()  
    {  
        return new Volunteer();  
    }  
}  
//客户端代码  
public class Main  
{  
    public static void main(String[] args)  
    {  
    
    
    //要换成“社区志愿者”修改这里就可以了
    //只需要修改一处就可以了,这是最佳的做法
    
    
        IFactory factory = new UndergraduateFactory();  
        LeiFeng student = factory.createLeiFeng();  
  
        student.buyRice();  
        student.sweep();  
        student.wash();  
    }  
}  
  • 总结:
    • 他们都是集中封装了对象的创建,使得要更换对象时候,不需要做大的改动就能实现,降低了客户端与产品对象的耦合
    • 工厂模式使简单工厂模式的进一步抽象和推广

3.策略模式--算法独立于使用它的客户而变化

  • Context: 环境类
  • Strategy: 抽象策略类
  • Strategy: 抽象策略类

它定义了算法家族,分别封装起来,让他们之间可以相互替换,此模式让算法的变化,不会影响使用算法的客户。

参考:http://hjxandhmr.github.io/2016/06/10/DesignPattern-Strategy/