简体   繁体   中英

strategy pattern no access to getters

Structure

-ClassA
|---|
|---ClassAImplA
|---ClassAImplB
-Main

Class A:

public interface ClassA {

    public void execute();

}

Implementaion A:

public class ClassAImplA implements ClassA 
{
    private int a = 5;

    public ClassAImplA (int a){setA(a);}
    @Override
    public void execute() {
        System.out.println(a);

    }
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }

Implementaion B:

public class ClassAImplB implements ClassA 
{
    private boolean b = false;

     public ClassAImplB (int a){setB(b);}
    @Override
    public void execute() {
        System.out.println(b);

    }
    public booelan getB() {
        return b;
    }
    public void setA(boolean b) {
        this.b = b;
    }   

main:

public class main {

    /**
     * @param args
     */
    public static  void main(String[] args) {
        ClassAImplA param1 = new ClassAImplA(10);
        ClassA = param1;
    }


}

By doing this I make ClassA interchangeable, but I lose the capability to access the parameter int a . Is there a way to still make it interchangeable, and still have access to int a , or in case of ClassAImplB , the field boolean b ?

There is a way, but it's not a good idea to do, as it defeats the purpose:

ClassAImplA param1 = new ClassAImplA(10);
ClassA = param1;
if (param1 instanceof ClassAImplA) {
    param1x = (ClassAImplA) param1;
    System.out.println(param1x.getA());
}

But don't do this. It defeats the purpose of the pattern. The purpose of the pattern is to use objects of type ClassA , without having to know how they work. The getA method is only defined in ClassAImplA , it's an implementation detail that should not be relevant to users of the ClassA type. They shouldn't have to know. It's hidden. This is called good encapsulation and information hiding.

you need one more class using composition to decide which implementation is needed.

 public ClassHelper{
     private A a;

     public ClassHelper(A a){
      this.a = a;
     }

     public void execute() {
      this.a.execute();
}


 }  


  public class main {

/**
 * @param args
 */
public static  void main(String[] args) {
    ClassHelper param1 = new ClassHelper(new ClassAImplA(10));
    param1.execute();

   //or when you need classBIMpl

   param1 = new ClassHelper(new ClassAImplB(true));
    param1.execute();


}

}

And about the ability to access member of implA or implB , no you cannot have that flexibilty with this patter, whole point of this pattern is that caller need not be aware of implementation details.

Define an interface for the strategy and a Factory with different overloaded methods to create the concrete instances of the classes. Of course the methods are typed to the interface instead of the concrete classes.

The interface.

public interface Strategy {
  void execute();
}

The first implementation.

public class ConcreteStrategy implements Strategy {

  private boolean a;

  public ConcreteStrategy(final boolean a) { this.a = a; }

  public void execute() {}
}

The second implementation.

public class AnotherConcreteStrategy implements Strategy {

  private int a;

  public AnotherConcreteStrategy(final int a) { this.a = a; }

  public void execute() {}
}

The factory.

public class Factory {

  public static Strategy create(final boolean a) {
    return new ConcreteStrategy(a);
  }

  public static Strategy create(final int a) {
    return new AnotherConcreteStrategy(a);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM