android设计模式-工厂模式

简单工厂模式:一个抽象产品类,可以派生出多个具体产品类。一个具体工厂类,通过往此工厂的static方法中传入不同参数,产出不同的具体产品类实例。

工厂方法模式:一个抽象产品类,可以派生出多个具体产品类。一个抽象工厂类,可以派生出多个具体工厂类。每个具体工厂类只能创建一个具体产品类的实例。

抽象工厂模式: 多个抽象产品类,每个抽象产品类可以派生出多个具体产品类。    一个抽象工厂类,可以派生出多个具体工厂类。    每个具体工厂类可以创建多个具体产品类的实例。

总的来说就是在工厂中new 具体实现的子类-产品的具体实现。而对于用户,不关心他是怎么生成的,只需要关注工厂即可。所有的new 对象都在工厂。后面的去new工厂的时候调用理解成多态。

同时注意产品或工厂的方法抽象出来。

直接是实体工厂去new的设计模式叫简单工厂

有个工厂抽象类,并每个产品都有一个工厂去生产new 对象 叫工厂方法

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

不需要生产一个产品就弄一个实体工厂。如果有新的东西过来,同样定义一个抽象工厂(和下面的对应,这是工厂方法),然后用之前的工程去new 出对象抽象工厂放抽象产品的接口或抽象对象,new回去才能调到产品那边

工厂方法和抽象工厂区别就是,工厂方法只生成一个产品,抽象工厂生成多个。简单点就是Factcty的那个接口或者类。加一个还是多个抽象产品类或接口,加多个就是抽象方法。加一个就是工厂方法

1.定义:在基类中定义创建对象的一个接口,让子类决定实例化哪个类。工厂方法让一个类的实例化延迟到子类中进行。

2.分类:
(1)简单工厂,又称静态工厂方法模式。
(2)工厂方法,又称多态性工厂模式。
(3)抽象工厂,又称工具箱模式。

3.为什么要使用工厂模式
(1)解耦:把对象的创建和使用过程分开。
(2)降低代码重复:如果创建某个对象的过程都很复杂,需要一定的代码量,而且很多地方都要用到,那么就会有很多的重复代码。
(3)降低维护成本:由于创建过程都由工厂统一管理,所以发生业务逻辑变化,不需要找到所有需要创建对象B的地方去逐个修正,只需要在工厂里修改即可,降低维护成本。

二、简单工厂模式

1.适用场景:
(1)需要创建的对象较少
(2)客户端不关心对象的创建过程

2.简单工厂模式的角色分配:
(1)工厂(Factory)角色 :简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类可以被外界直接调用,创建所需的产品对象。
(2)抽象产品(Product)角色 :简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
(3)具体产品(Concrete Product)角色:简单工厂模式的创建目标,所有创建的对象都是充当这个角色的某个具体类的实例

3.简单工厂实例
eg:创建一个可以绘制不同形状的绘图工具,可以绘制圆形,正方形,三角形,每个图形都会有一个draw()方法用于绘图。

(1)创建Shape接口

public interface Shape {
    void draw();
}

(2)创建实现该接口的集体图形类

public class Circle implements Shape {
    public Circle(){
        System.out.println("Circle");
    }

    @Override
    public void draw() {
        System.out.println("Draw Circle");
    }
}

public class Rectangle implements Shape {

    public Rectangle(){
        System.out.println("Rectangle");
    }
    @Override
    public void draw() {
        System.out.println("Draw Rectangle");
    }
}

public class Square implements Shape {
    public Square() {
        System.out.println("Square");
    }

    @Override
    public void draw() {
        System.out.println("Draw Square");
    }
}

(3)创建工厂类

public class ShapeFactory {
    public static Shape createShape(String shapeType) { //注意是用的接口或者抽象类作为修饰对象!!!
        if (shapeType == null) {
            return null;
        }
        if (shapeType.equalsIgnoreCase("CIRCLE")) {
            return new Circle();
        } else if (shapeType.equalsIgnoreCase("RECTANGLE")) {
            return new Rectangle();
        } else if (shapeType.equalsIgnoreCase("SQUARE")) {
            return new Square();
        }
        return null;
    }
}

(4)测试

@Test
public void test() {
    // 获取 Circle 的对象,并调用它的 draw 方法
    Shape circle = ShapeFactory.createShape("CIRCLE");
    circle.draw();

    // 获取 Rectangle 的对象,并调用它的 draw 方法
    Shape rectangle = ShapeFactory.createShape("RECTANGLE");
    rectangle.draw();

    // 获取 Square 的对象,并调用它的 draw 方法
    Shape square = ShapeFactory.createShape("SQUARE");
    square.draw();
}

结果:
Circle
Draw Circle
Rectangle
Draw Rectangle
Square
Draw Square

这样的实现有个问题,如果我们新增产品类的话,就需要修改工厂类中的getShape()方法,这很明显不符合 开放-封闭原则

4.使用反射机制改善简单工厂

public class ShapeFactory {
    public static Object createShape(Class<? extends Shape> tClass) {
        Object obj = null;
        try {
            obj = Class.forName(tClass.getName()).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return obj;

    }
}

测试:

@Test
public void test() {
    // 获取 Circle 的对象,并调用它的 draw 方法
    Shape circle = (Shape) ShapeFactory.createShape(Circle.class);
    circle.draw();

    // 获取 Rectangle 的对象,并调用它的 draw 方法
    Shape rectangle = (Shape) ShapeFactory.createShape(Rectangle.class);
    rectangle.draw();

    // 获取 Square 的对象,并调用它的 draw 方法
    Shape square = (Shape) ShapeFactory.createShape(Square.class);
    square.draw();
}

三、工厂方法模式

工厂方法模式是简单工厂的仅一步深化, 在工厂方法模式中,我们不再提供一个统一的工厂类来创建所有的对象,而是针对不同的对象提供不同的工厂。也就是说 每个对象都有一个与之对应的工厂

1.适用场景:
(1)一个类不知道它所需要的对象的类:在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建;客户端需要知道创建具体产品的工厂类。
(2)一个类通过其子类来指定创建哪个对象:在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏

2.工厂方法角色分配:
(1)抽象工厂(Abstract Factory)角色:是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
(2)具体工厂(Concrete Factory)角色 :这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象。
(3)抽象产品(AbstractProduct)角色 :工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
(4)具体产品(Concrete Product)角色 :这个角色实现了抽象产品角色所定义的接口。某具体产品有专门的具体工厂创建,它们之间往往一一对应

3.实例

(1)增加一个工厂接口:

public interface Factory {
    public Shape getShape();
}

(2)增加相关工厂类:

圆形工厂类

public class CircleFactory implements Factory {

    @Override
    public Shape getShape() {
        // TODO Auto-generated method stub
        return new Circle();
    }

}

长方形工厂类

public class RectangleFactory implements Factory{

    @Override
    public Shape getShape() {
        // TODO Auto-generated method stub
        return new Rectangle();
    }

}

圆形工厂类

public class SquareFactory implements Factory{

    @Override
    public Shape getShape() {
        // TODO Auto-generated method stub
        return new Square();
    }

}

(3)测试:

public class Test {

    public static void main(String[] args) {
        Factory circlefactory = new CircleFactory();
        Shape circle = circlefactory.getShape();
        circle.draw();
    }

}

输出结果:

Circle
Draw Circle

四、抽象工厂模式
在工厂方法模式中,其实我们有一个潜在意识的意识。那就是我们生产的都是同一类产品。抽象工厂模式是工厂方法的仅一步深化,在这个模式中的工厂类不单单可以创建一种产品,而是可以创建一组产品。

1.适用场景
(1)和工厂方法一样客户端不需要知道它所创建的对象的类。
(2)需要一组对象共同完成某种功能时,并且可能存在多组对象完成不同功能的情况。(同属于同一个产品族的产品)
(3)系统结构稳定,不会频繁的增加对象。(因为一旦增加就需要修改原有代码,不符合开闭原则)

2.抽象工厂的角色分配
(1)抽象工厂(AbstractFactory)角色 :是工厂方法模式的核心,与应用程序无关。任何在模式中创建的对象的工厂类必须实现这个接口。
(2)具体工厂类(ConreteFactory)角色 :这是实现抽象工厂接口的具体工厂类,包含与应用程序密切相关的逻辑,并且受到应用程序调用以创建某一种产品对象。
(3)抽象产品(Abstract Product)角色 :工厂方法模式所创建的对象的超类型,也就是产品对象的共同父类或共同拥有的接口。
(4)具体产品(Concrete Product)角色 :抽象工厂模式所创建的任何产品对象都是某一个具体产品类的实例。在抽象工厂中创建的产品属于同一产品族,这不同于工厂模式中的工厂只创建单一产品。

3.抽象工厂与工厂方法有什么区别?
抽象工厂是生产一整套有产品的(至少要生产两个产品),这些产品必须相互是有关系或有依赖的,而工厂方法中的工厂是生产单一产品的工厂。

4.抽象工厂实例
不知道大家玩过穿越火线或者吃鸡这类游戏了吗,游戏中存在各种枪。我们假设现在存在AK、M4A1两类枪,每一种枪对应一种子弹。我们现在这样考虑生产AK的工厂可以顺便生产AK使用的子弹,生产M4A1的工厂可以顺便生产M4A1使用的子弹。(AK工厂生产AK系列产品包括子弹啊,AK枪的类型啊这些,M4A1工厂同理)

(1)创建相关接口:

public interface Gun {
    public void shooting();
}

子弹

public interface Bullet {
    public void load();
}

(2)创建接口对应实现类:

AK类

public class AK implements Gun{

    @Override
    public void shooting() {
        System.out.println("shooting with AK");
        
    }

}

M4A1类

public class M4A1 implements Gun {

    @Override
    public void shooting() {
        System.out.println("shooting with M4A1");

    }

}

AK子弹类

public class AK_Bullet implements Bullet {

    @Override
    public void load() {
        System.out.println("Load bullets with AK");
    }

}

M4A1子弹类

public class M4A1
_Bullet implements Bullet {

    @Override
    public void load() {
        System.out.println("Load bullets with M4A1");
    }

}

(3)创建工厂接口

public interface Factory {
    public Gun produceGun();
    public Bullet produceBullet();
}

(4)创建具体工厂

生产AK和AK子弹的工厂

public class AK_Factory implements Factory{

    @Override
    public Gun produceGun() {
        return new AK();
    }

    @Override
    public Bullet produceBullet() {
        return new AK_Bullet();
    }

}

生产M4A1和M4A1子弹的工厂

public class M4A1_Factory implements Factory{

    @Override
    public Gun produceGun() {
        return new M4A1();
    }

    @Override
    public Bullet produceBullet() {
        return new M4A1_Bullet();
    }

}

(5)测试

public class Test {

    public static void main(String[] args) {  
        
     Factory factory;
     Gun gun;
     Bullet bullet;
     
     factory =new AK_Factory();
     bullet=factory.produceBullet();
     bullet.load();
     gun=factory.produceGun();
     gun.shooting(); 
     
    }

}

输出结果:

Load bullets with AK
shooting with AK

下面这个例子更加明显:

//---------------------之前没变的代码区域---------------------//


//登陆接口(没变)也可以是抽象类
public interface ILogin {
    void login();
}

//QQ登陆实现(没变)
public class QQLogin implements ILogin {
    @Override
    public void login() {
        System.out.println("QQ登陆...");
    }
}

//WeiXin登陆实现(没变)
public class WeiXinLogin implements ILogin {
    @Override
    public void login() {
        System.out.println("微信登陆...");
    }
}
//其他第三方登陆同上,省略...


//上面定义的支付接口(没变)也可以是抽象类
public interface IPay {
    void pay();
}

//支付宝支付实现(没变)
public class AliPay implements IPay {
    @Override
    public void pay() {
        System.out.println("支付宝支付...");
    }
}

//微信支付实现(没变)
public class WeiXinPay implements IPay {
    @Override
    public void pay() {
        System.out.println("微信支付...");
    }
}
//其他支付同上,省略...

//---------------------之前没变的代码区域end---------------------//

//----------------工厂类和工厂接口换个角度设计(彻底改头换脸)----------------//

//工厂接口(之前只有登陆一种类型方法,现在从登陆和绑定支付2种类型考虑设计接口)也可以是抽象类
public interface IFactory {                      // public interface IFactory {
     ILogin initQQLogin();     //======和之前对比》//       ILogin initLogin(); 调用关系:多态 子类继承或者实现抽象类或者接口。所以给他new 父类= new 子类 

父类型的应用可以指向子类型的对象

比如 Parent P = new Child();

都是产品的接口或抽象方法

抽象工厂就放产品的抽象类或接口

     ILogin initWeiXinLogin();                   //  }

     IPay bindAliPay();
     IPay bindWeiXinPay();
}

//工厂实现类
public class FactoryImp implements IFactory{
    @Override
    public ILogin initQQLogin() {
        return new QQLogin();
    }

    @Override
    public ILogin initWeiXinLogin() {
        return new WeiXinLogin();
    }

    @Override
    public IPay bindAliPay() {
        return new AliPay();
    }

    @Override
    public IPay bindWeiXinPay() {
        return new WeiXinPay();
    }


}

  //使用
  FactoryImp factoryImp = new FactoryImp();

// 可以理解成 ILogin a = new  factoryImp.initQQLogin()

                      ILogin a = new QQLogin()

                     a.login()父类引用指向子类的实现

  factoryImp.initQQLogin().login();
  factoryImp.initWeiXinLogin().login();

  factoryImp.bindAliPay().pay();
  factoryImp.bindWeiXinPay().pay();

如果还要增加工厂,相对于工厂方法来说,就不需要给每个产品去建立工厂了。直接用原有的工厂就能够生产出来。

//新加的新浪微博登陆
public class SinaLogin implements ILogin {
    @Override
    public void login() {
        System.out.println("新浪微博登陆...");
    }
}
//新加的银行支付
public class BankPay implements IPay {
    @Override
    public void pay() {
        System.out.println("银行支付...");
    }
}

//新加的接口(也可以是抽象类)
public interface INewFactory {
    ILogin initSinaLogin();

    IPay bindBankPay();
}

//新加的抽象工厂类,在原来基础上面新加的接口,搞定
public class NewFactoryImp implements IFactory,INewFactory{
    @Override
    public ILogin initQQLogin() {
        return new QQLogin();
    }

    @Override
    public ILogin initWeiXinLogin() {
        return new WeiXinLogin();
    }

    @Override
    public IPay bindAliPay() {
        return new AliPay();
    }

    @Override
    public IPay bindWeiXinPay() {
        return new WeiXinPay();
    }


    @Override
    public ILogin initSinaLogin() {
        return new SinaLogin();
    }

    @Override
    public IPay bindBankPay() {
        return new BankPay();
    }
}

//使用还是一样,省略...
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/u014769864/article/details/78297248


作者:大漠孤烟直_v
链接:https://www.jianshu.com/p/37c7745877a0
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 14
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值