模式设计之工厂模式

来源:互联网 发布:网络博客被骗怎么追 编辑:程序博客网 时间:2024/04/30 01:11
      最近在学习设计模式,由于在做android之前是写linux C代码的,思维一直停留在函数阶段,所以对面向对象设计理解不深。静下来,发现自己项目中的代码,不仅冗余度比较高,而且设计比较混乱,如果需求变更,项目改动往往都改动比较大。

     由于项目主要都是智能家居WiFi控制类,再同一个APP中会存在对多种设备的控制,所以这里面就有一个问题,区分不同的设备。以前的做法就是做一个函数,各种switch 各种if判断,如果有新产品增加,那就必须又增加一个if判断,或者说如果需要将其中的两种或者三种设备放在同一个界面显示,那只有另外起一个函数。这样不仅麻烦,而且容易对以前OK的功能产生影响。

现在对项目中已有的做法进行改进。
简单工厂模式:
首先是改成简单工厂模式:
UML图
好了 那我们就开始编码吧。

首先当然是建立一个设备接口
public interface Device{
       //获取设备列表信息
       List<device> getDeviceList();
}

然后是建立具体的设备产品
//设备类型1对抽象产品接口的实现
public class deviceType1 implements Device {

 @Override
 public List<device> getDeviceType() {
    List<device> list=new ArrayList<device>;
     //此处实现获取设备类型1的方法。 
   System.out.println("获取设备类型1");
     return list ;
 }
}

//设备类型2对抽象产品接口的实现
public class deviceType2 implements Device {

 @Override
 public List<device> getDeviceType() {
    List<device> list=new ArrayList<device>;
     //此处实现获取设备类型2列表的方法。 
   System.out.println("获取设备类型2");
     return list ;
 }
}

//设备类型3对抽象产品接口的实现
public class deviceType3 implements Device {

 @Override
 public List<device> getDeviceType() {
    List<device> list=new ArrayList<device>;
     //此处实现获取设备类型3列表的方法。 
    System.out.println("获取设备类型3");
     return list ;
 }
}

设备类型实现完成了,现在该建立一个生产这些设备的工程了。

public class deviceFactory{

    List<Device> list=new ArrayList<Device>;
 public static list<device> getDeviceType(int devicetype){
    switch(devicetype){
    case 1:
        deviceType1 mdt1=new deviceType1 ();
         list=mdt1.getDeviceType();
         break;
     case 2:     
        deviceType2 mdt2=new deviceType2 ();
         list=mdt2.getDeviceType();
         break;
     case 3:
        deviceType3 mdt3=new deviceType3();
         list=mdt3.getDeviceType();
         break;
}
return list;
}
}

最后就是具体使用啦。
    deviceFactory.getDeviceType(1);
    deviceFactory.getDeviceType(2);
    deviceFactory.getDeviceType(3);

好了,一个简单工厂模式就设计完成了,
     这样设计的优点就是,在工厂类中提供了必要的逻辑判断,能够给外界提示决定究竟该创建哪个设备类型的设备,而不需要去了解他究竟是如何生成这些特定list的。
      但是又发现 ,由于这个工厂类中集成了所有的设备类型的实现方式,一旦这个工厂类出现问题,则整个客户端都会受到牵连,如果随着设备类型的不断增加 ,我的工厂类中就需要不停的添加判断。这明显违背了“开放封闭原则”

工厂方法模式:
那下面我们对这个设计模式继续优化。下面用到的就是工厂模式中的工厂方法模式。
下面先简单介绍一下工厂方法模式:
          工厂方法模式(Factory Method Pattern)属于类的创建型模式又被称为多态工厂模式(Polymorphic) 。
工厂方法模式的意义是定义一个创建产品对象的工厂接口,将实际创建工作推迟到子类当中。核心工厂类不再负责产品
的创建,这样核心类成为一个抽象工厂角色,仅负责具体工厂子类必须实现的接口,这样进一步抽象化的好处是使得工
厂方法模式可以使系统在不修改具体工厂角色的情况下引进新的产品。 
 首先还是先上UML图

由于之前不同设备类型的实现已经做了 这里我就不在添加这些代码了。只将改动的部分加上。
首先需要一个设备工厂的抽象方法。

public interface Factory{
  //设备工厂中获得相应的设备
  Device getDevice();
}

设备类型1工厂的实现

public class deviceType1Factory implements Factory {
 @Override
 public Device getDevice() {
     return new deviceType1 ();
 }

}

设备类型2工厂的实现

public class deviceType2Factory implements Factory {
 @Override
 public Device getDevice() {
  return new deviceType2 ();
 }

}


设备类型3工厂的实现

public class deviceType3Factory implements Factory {
 @Override
 public Device getDevice() {
  return new deviceType3 ();
 }

}

3.好了 ,下面就是使用了。
  deviceType1Factory  mdeviceType1Factory=new deviceType1Factory();
  mdeviceType1Factory.getDevice();
   
 deviceType2Factory  mdeviceType2Factory=new deviceType2Factory();
  mdeviceType2Factory.getDevice();

 deviceType3Factory  mdeviceType3Factory=new deviceType3Factory();
  mdeviceType3Factory.getDevice();

到此为止工厂方法模式就已经设计完成了。
        该模式的优点就是 工厂方法类的核心就是一个抽象工厂方法,所有的工厂方法必须实现该抽象方法,这样当有新的设备类型添加进来的时候,仅仅需要添加一个具体的设备类型对象和一个具体的设备类型工厂对象,原有工厂对象不需要进行修改,这样也不影响到客户端以后的设备类型。这比较符合面向对象设计中的“开放封闭”原则。
        缺点就是客户端需要自己决定去使用哪个工厂对象,也就是说将简单工厂模式中的类型判断改成由客户端自己判断了,而且每增加一个类型就需要实例化一个该设备类型的工厂方法。这样会使工作量增加。
总结:在此例中,虽然工厂方法模式会增加工作量,但是提供了很好的可维护性。虽然增加了代码量,但是其实也没有增加多少。


抽象工厂模式
工厂方法模式中还有一种抽象工厂模式。
假设现在项目中需要区分用户A的设备类型1,2,3 ,用户B的设备类型1,2,3,那在现有的设计模式就不好扩展了。
这个时候就需要用到抽象工厂模式了。
抽象工厂模式可以向客户端提供一个接口,使得客户端可以在不必指定产品类型的情况下,创建产品族、
UML图如下:
编码:
Device接口
public interface Device {

 List<Device> getDeviceType();
}
用户工厂接口
public interface Factory2 {

 Device getDeviceType1();
 
 Device getDeviceType2();

}
//设备类型1的抽象父类
public abstract class DeviceType1 implements Device {

 @Override
 public List<Device> getDeviceType() {
  // TODO Auto-generated method stub
  return null;
 }
}

//设备类型2的抽象父类
public abstract class DeviceType2 implements Device {

 @Override
 public List<Device> getDeviceType() {
  // TODO Auto-generated method stub
  return null;
 }
}

//建立张三的设备类型1
public class zhangsanDeviceType1 extends DeviceType1{

 @Override
 public List<Device> getDeviceType() {
  //此处获取张三的DeviceType1
  return null;
 }
}

//建立张三的设备类型2 
public class zhangsanDeviceType2 extends DeviceType2{

 @Override
 public List<Device> getDeviceType() {
  //此处获取张三的DeviceType2
  return null;
 }
}

//建立李四的设备类型1
public class lisiDeviceType1 extends DeviceType1{

 @Override
 public List<Device> getDeviceType() {
  //此处获取李四的DeviceType1
  return null;
 }
}

//建立李四的设备类型1 
public class lisiDeviceType2 extends DeviceType2{

 @Override
 public List<Device> getDeviceType() {
  //此处获取李四的DeviceType2
  return null;
 }
}

//建立张三的工厂
public class zhangsanFactory implements Factory2 {
 @Override
 public Device getDeviceType1() {
  // TODO Auto-generated method stub
  return new zhangsanDeviceType1();
 }
 @Override
 public Device getDeviceType2() {
  // TODO Auto-generated method stub
  return new zhangsanDeviceType2();
 }
}

//建立李四的工厂
public class lisiFactory implements Factory2 {
 @Override
 public Device getDeviceType1() {
  // TODO Auto-generated method stub
  return new lisiDeviceType1();
 }
 @Override
 public Device getDeviceType2() {
  // TODO Auto-generated method stub
  return new lisiDeviceType2();
 }
}

客户端调用:
  zhangsanFactory zsf=new zhangsanFactory();
  zsf.getDeviceType1().getDeviceType();
  zsf.getDeviceType2().getDeviceType();
 
  lisiFactory lsf=new lisiFactory();
  lsf.getDeviceType1().getDeviceType();
  lsf.getDeviceType2().getDeviceType();


总结:
     优点:客户端不再负责对象的具体创建,而是把这个责任交给了具体的工厂类,客户端只负责对对象的调用。当具
有产品家族性质的产品被涉及到一个工厂类中后,对客户端而言是非常友好的,更重要的是如果想要更换为另外一产品
家族,所要做的只是需要增加相应的产品家族成员和增加一个具体的产品工厂而已。
      缺点:当有新的产品加入的时候,也就是当产品的结构发生改变时,要修改抽象工厂类的设计,这就导致了必须
修改所有的具体工厂类,导致很客观的工作量的增加。
   







0 0
原创粉丝点击