美文网首页androidJAVA设计模式互联网科技
Android 架构师2 设计模式之原型模式

Android 架构师2 设计模式之原型模式

作者: zhang_pan | 来源:发表于2018-04-09 15:44 被阅读58次

前言

Prototype原型模式属于创建型模式。用原型的实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。Prototype原型模式允许一个对象再创建另外一个可定制的对象,根本无需知道任何如何创建的细节,工作原理是:通过将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝它们自己来实施创建。

需求

某个客户产生一个订单,订单有产品的数量、产品的名称,公司接收订单并进入内部处理系统。
要求先保留最原始的一份数据作为存根,一个生产部门最多生产100个产品。

基本实现

订单接口IOrder:

public interface IOrder {
    void setOrderNum(int num);
    int getOrderNum();

    void setOrderName(String name);
    String getOrderName();
}

个人订单类PersonalOrder:

public class PersonnalOrder implements IOrder {
    private int orderNum;
    private String orderName;

    @Override
    public void setOrderNum(int num) {
        this.orderNum = num;
    }

    @Override
    public int getOrderNum() {
        return this.orderNum;
    }

    @Override
    public void setOrderName(String name) {
        this.orderName = name;
    }

    @Override
    public String getOrderName() {
        return this.orderName;
    }
}

工厂接口IOrderDealFactory:

public interface IOrderDealFactory {
    void dealOrder(IOrder order);
}

订单生产工厂类OrderDealFactory:

public class OrderDealFactory implements IOrderDealFactory {

    @Override
    public void dealOrder(IOrder order) {
        System.out.println("原始订单地址:" + order.hashCode());
        PersonalOrder personalOrderStub = (PersonalOrder) order;
        int orderNum = personalOrderStub.getOrderNum();

        while (orderNum > 0) {
            PersonalOrder personalOrder = new PersonalOrder();
            personalOrder.setOrderName(personalOrderStub.getOrderName());
            personalOrder.setOrderNum(orderNum > 100 ? 100 : orderNum);
            orderNum -= 100;
            System.out.println("生产订单:" + personalOrder.hashCode() + "," + personalOrder.getOrderName() + ", " + personalOrder.getOrderNum());
        }
    }
}

接下来我们来模拟一个客户订单场景类Client:

public class Client {
    public static void main(String[] args) {
        OrderDealFactory factory = new OrderDealFactory();
        PersonalOrder personalOrder = new PersonalOrder();
        personalOrder.setOrderName("个人订单");
        personalOrder.setOrderNum(430);
        factory.dealOrder(personalOrder);
    }
}

这样,基本上需求已经完成:

原始订单地址:356573597
生产订单:1735600054,个人订单, 100
生产订单:21685669,个人订单, 100
生产订单:2133927002,个人订单, 100
生产订单:1836019240,个人订单, 100
生产订单:325040804,个人订单, 30

新增需求

这时候,又来了一个公司订单,我们可能会这样做:
新增一个公司订单类CompanyOrder:

public class CompanyOrder implements IOrder {
    private int orderNum;
    private String orderName;

    @Override
    public void setOrderNum(int num) {
        this.orderNum = num;
    }

    @Override
    public int getOrderNum() {
        return this.orderNum;
    }

    @Override
    public void setOrderName(String name) {
        this.orderName = name;
    }

    @Override
    public String getOrderName() {
        return this.orderName;
    }
}

有人要说了,这个CompanyOrder类和PersonalOrder除了名字不一样而已,其他都是一样啊,其实不然,我们只不过简化了具体的内容,其实两个类里面还应该存在其他的业务逻辑,只不过我们省略了而已,而这部分正是两者的不同之处。

修改OrderDealFactory类:

public class OrderDealFactory implements IOrderDealFactory {

    @Override
    public void dealOrder(IOrder order) {
        System.out.println("原始订单地址:" + order.hashCode());
        if (order instanceof PersonalOrder) {
            PersonalOrder personalOrderStub = (PersonalOrder) order;
            int orderNum = personalOrderStub.getOrderNum();

            while (orderNum > 0) {
                PersonalOrder personalOrder = new PersonalOrder();
                personalOrder.setOrderName(personalOrderStub.getOrderName());
                personalOrder.setOrderNum(orderNum > 100 ? 100 : orderNum);
                orderNum -= 100;
                System.out.println("生产订单:" + personalOrder.hashCode() + "," + personalOrder.getOrderName() + ", " + personalOrder.getOrderNum());
            }
        } else if (order instanceof CompanyOrder) {
            CompanyOrder companyOrderStub = (CompanyOrder) order;
            int orderNum = companyOrderStub.getOrderNum();

            while (orderNum > 0) {
                CompanyOrder companyOrder = new CompanyOrder();
                companyOrder.setOrderName(companyOrderStub.getOrderName());
                companyOrder.setOrderNum(orderNum > 100 ? 100 : orderNum);
                orderNum -= 100;
                System.out.println("生产订单:" + companyOrder.hashCode() + "," + companyOrder.getOrderName() + ", " + companyOrder.getOrderNum());
            }
        }
    }
}

这样做,虽然能够满足需求,但是如果再来一个其他种类的订单呢?我们是不是还需要修改OrderDealFactory类,我们要知道设计模式的原则是对修改关闭,对拓展开放,而这里我们其实是违背了这个原则,那我们应该怎么做呢?接下来来看原型模式怎么去解决这个问题:

原型模式

新增一个原型复制接口Prototype :

public interface Prototype {
    Prototype cloneOrder();
}

IOrder继承这个接口:

public interface IOrder extends Prototype {
    void setOrderNum(int num);
    int getOrderNum();

    void setOrderName(String name);
    String getOrderName();
}

这样PersonalOrder和CommpanyOrder就必须重写这个接口中的方法:
PersonalOrder:

public class PersonalOrder implements IOrder {
    private int orderNum;
    private String orderName;

    @Override
    public void setOrderNum(int num) {
        this.orderNum = num;
    }

    @Override
    public int getOrderNum() {
        return this.orderNum;
    }

    @Override
    public void setOrderName(String name) {
        this.orderName = name;
    }

    @Override
    public String getOrderName() {
        return this.orderName;
    }

    @Override
    public Prototype cloneOrder() {
        PersonalOrder personalOrder = new PersonalOrder();
        personalOrder.setOrderName(orderName);
        personalOrder.setOrderNum(orderNum);
        return personalOrder;
    }
}

CommpanyOrder:

public class CompanyOrder implements IOrder {
    private int orderNum;
    private String orderName;

    @Override
    public void setOrderNum(int num) {
        this.orderNum = num;
    }

    @Override
    public int getOrderNum() {
        return this.orderNum;
    }

    @Override
    public void setOrderName(String name) {
        this.orderName = name;
    }

    @Override
    public String getOrderName() {
        return this.orderName;
    }

    @Override
    public Prototype cloneOrder() {
        CompanyOrder companyOrder = new CompanyOrder();
        companyOrder.setOrderName(orderName);
        companyOrder.setOrderNum(orderNum);
        return companyOrder;
    }
}

此时我们的工厂类OrderDealFactory :

public class OrderDealFactory implements IOrderDealFactory {

    @Override
    public void dealOrder(IOrder order) {
        int orderNum = order.getOrderNum();
        System.out.println("原始订单地址:" + order.hashCode());
        while (orderNum > 0) {
            IOrder iorder = (IOrder) order.cloneOrder();
            iorder.setOrderNum(orderNum > 100 ? 100 : orderNum);
            orderNum -= 100;
            System.out.println("生产订单:" + iorder.hashCode() + "," + iorder.getOrderName() + ", " + iorder.getOrderNum());
        }
}

我们调用的时候传入PersonablOrder或者CompanyOrder,通过IOrder iorder = (IOrder) order.cloneOrder()获得该对象,这样就无需继续判断属于哪一种类型了。
这时候我们回过头来看工厂类,是不是很简单,而且以后新增不同种类的订单,也无须修改这个工厂类,只需要新增不同种类的订单类,满足了设计模式的原则。

浅拷贝和深拷贝

对于浅拷贝和深拷贝,我在此就不逐一举例了,不清楚内部工作原理的,可以查看博客设计模式之原型模式,大致可以总结如下:

浅拷贝: 对基本数据类型的成员变量进行值的复制,对引用类型的成员变量只复制引用(地址相同),不复制引用的对象(内容不同)。
深拷贝: 对基本数据类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制(地址和内容都不同)。

原型模式在Android中的应用

Intent源码就是采用的原型模式:

1.png

总结

原型模式虽然简单,但是在实际生活中还是会经常用到的,经常配合工厂模式综合应用。

喜欢本篇博客的简友们,就请来一波点赞,您的每一次关注,将成为我前进的动力,谢谢!

相关文章

网友评论

    本文标题:Android 架构师2 设计模式之原型模式

    本文链接:https://www.haomeiwen.com/subject/icwbhftx.html