How to enforce sequence in function calls

后端 未结 4 640
北荒
北荒 2021-01-07 22:44

Let\'s say I want to design a class whose clients would need to call functions in a particular sequence, e.g.,

hasNext();
next();

or, as a

相关标签:
4条回答
  • 2021-01-07 23:26

    You might be interested in the Step Builder Pattern. It's not necessarily a good match for all the cases that you've presented, but the idea is that each operation returns something implementing an interface that lets you perform the next operation. Since you can only get the objects by performing the operations in the correct order, you'll be forced to perform them in the correct order.

    While it would feel a bit forced in the iteration (next/hasNext) situation, you can imagine it for the

    • put on your socks,
    • then put on your shoes

    pattern. Somehow you get an instance of the CanWearSocks interface, which has only the following method.

    CanWearShoes putOnSocks()
    

    When you call putOnSocks(), you get your CanWearShoes instance, which has only the following method.

    SockAndShoeWearer putOnShoes()
    

    When you call putOnShoes() you now have something wearing socks and shoes, and you were forced to do it in the correct order.

    What's particularly nice is that you can actually use the same object in both cases, but because the method signatures only return the interface type, code will only be able to use the interface methods (unless the code is sneaky, and casts the object to a different type).

    Example

    Here's a rather contrived example that implements the iteration pattern, i.e., that makes sure that you use a NextChecker before a NextGetter.

    public class StepBuilderIteration {
    
        interface NextChecker {
            NextGetter hasNext();
        }
    
        interface NextGetter {
            Object next();
            NextChecker more();
        }
    
        static class ArrayExample {
            final static Integer[] ints = new Integer[] { 1, 2, 3, 4 };
    
            public static NextChecker iterate() {
                return iterate( 0 );
            }
    
            private static NextChecker iterate( final int i ) {
                return new NextChecker() {
                    public NextGetter hasNext() {
                        if ( i < ints.length ) {
                            return new NextGetter() {
                                public Object next() {
                                    return ints[i];
                                }
                                public NextChecker more() {
                                    return iterate( i+1 );
                                }
                            };
                        }
                        else {
                            return null;
                        }
                    }
                };
            }
        }
    
        public static void main(String[] args) {
            NextChecker nc = ArrayExample.iterate();
            while (nc != null) {
                NextGetter ng = nc.hasNext();
                if (ng != null) {
                    System.out.println(ng.next());
                    nc = ng.more();
                }
            }
        }
    }
    

    The output is:

    1
    2
    3
    4
    
    0 讨论(0)
  • 2021-01-07 23:31

    If you have full access to the source code and you can modify it then what's preventing you from using a combination of Factory Method Pattern with Template Method Pattern. A simple example:

    public class CookFood {
    
        public Food MakeFood() {
            PrepareFood();
            HeatFood();
            ServeFood();
        }
    
        protected abstract void PrepareFood();
        protected abstract void HeatFood();
        protected abstract ServeFood();
    
    }
    

    Now clients of the code can call MakeFood which will enforce the order of steps and if you want to customize any step then you can subclass CookFood and implement that certain step. Of course the steps PrepareFood(), HeatFood(), ServeFood() need not be abstract, you can have a default implementation which you can override in the subclass for customization.

    0 讨论(0)
  • 2021-01-07 23:37

    There can be different approaches, one is listed here. Although this approach considers that you need to call the other function once before calling the other one but not always. You may edit it as per you need:

    1. Create variables to check the state of function calls. Whenever someone calls listOfItems then you can set the isListed variable to true. Then check the value of isListed in mixAllItems to be sure that getListOfItems was called earlier.

      class CookFood {
          boolean isListed;
          boolean isMixed;
          boolean isHeated;
      
          public String getListOfItems() {
      
              // do listing and mark as listed
              isListed = true;
      
              return "something";
          }
      
          public void mixAllItems() {
              // check if listed first
              if (isListed) {
                  // do mixing
      
                  // mark as mixed
                  isMixed = true;
              } else {
                  System.out.println("You need to call getListOfItems before mixing");
                  return;
              }
          }    
      
          public void heat() {
              if (isMixed) {
                  // do heating
      
                  // mark as mixed
                  isHeated = true;
              } else {
                  System.out.println("You need to call isMixed before heating");
                  return;
              }
          }
      }
      
    0 讨论(0)
  • 2021-01-07 23:42

    One way to do what you want is to set flags whenever a function is called, then checking if that flag is set when a dependant function is called.

    For example:

    public void getListOfItems() {
        funcGetListOfItemsCalled = true;
        ....
    }
    
    public void mixAllItems() {
        if(funcGetListOfItemsCalled) {
            funcMixAllItemsCalled = true;
            ...
        }
    }
    
    public void mixAllItems() {
        if(funcMixAllItemsCalled ) {
            ...
        }
    }
    
    0 讨论(0)
提交回复
热议问题