Unanswered Abstract factory redesign

  • quinta-feira, 2 de agosto de 2012 08:08
     
      Contém Código

    Hello

    For example, i have abstract factory of phones:

    public interface IPhone
    {
    	IBody CreatePhoneBody();
    	IConnection CreateConnection();
    }
    
    class MobilePhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new MobilePhoneBody();
    	}
    	
    	IConnection CreateConnection()
    	{
    		return new WirelesConnection();
    	}
    }
    
    class StreetCoinsPhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new StreetPhoneBody();
    	}
    	
    	IConnection CreateConnection()
    	{
    		return new WiredConnection();
    	}
    }


    All works fine, but mobile company get changed: wireless connection got be: WiFi and Bluetooth connections.

    i can see 2 solutions (both of them i did not like):

    1.

    enum WirelessType {WiFi, Bluetooth,}
    
    public interface IPhone
    {
    	IBody CreatePhoneBody();
    	IConnection CreateConnection(WirelessType type);
    }
    
    class MobilePhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new MobilePhoneBody();
    	}
    	
    	IConnection CreateConnection(WirelessType type)
    	{
    		if(type == WirelessType.WiFi)
    		{
    			return new WiFiConnection();
    		}
    		else if(type == WirelessType.Bluetooth)
    		{
    			return new BluetoothConnection();
    		}
    	}
    }
    
    class StreetCoinsPhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new StreetPhoneBody();
    	}
    	
    	IConnection CreateConnection(WirelessType type) //nothing to do with parameter
    	{
    		return new WiredConnection();
    	}
    }

    2.

    public interface IPhone
    {
    	IBody CreatePhoneBody();
    	IConnection CreateWiFiConnection();
    	IConnection CreateBluetoothConnection();
    }
    
    class MobilePhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new MobilePhoneBody();
    	}
    	
    	IConnection CreateWiFiConnection()
    	{
    		return new WiFiConnection();
    	}
    	
    	IConnection CreateBluetoothConnection()
    	{
    		return new BluetoothConnection();
    	}
    }
    
    class StreetCoinsPhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new StreetPhoneBody();
    	}
    	
    	IConnection CreateWiFiConnection()
    	{
    		return new WiredConnection(); //StreetCoinsPhone no wireless connection...
    	}
    	
    	IConnection CreateBluetoothConnection()
    	{
    		return new WiredConnection(); //StreetCoinsPhone no wireless connection...
    	}
    }

    As i say, i hate both of approaches. 

    How can i do it?

    Maybe my abstraction is changes? I can not see it.. My families here are Mobile and StreetCoins phones. It do not seems to be good idea to do Wired, WiFi and Bluetooth families... Like this:

    public interface IPhone
    {
    	IBody CreatePhoneBody();
    	IConnection CreateConnection();
    }
    
    class WiFiPhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new MobilePhoneBody();
    	}
    	
    	IConnection CreateConnection()
    	{
    		return new WiFiConnection();
    	}
    }
    
    class BluetoothPhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new MobilePhoneBody();
    	}
    	
    	IConnection CreateConnection()
    	{
    		return new BluetoothConnection();
    	}
    }
    
    class WiredPhone: IPhone
    {
    	IBody CreatePhoneBody()
    	{
    		return new StreetPhoneBody();
    	}
    	
    	IConnection CreateConnection()
    	{
    		return new WiredConnection();
    	}
    }
    Or, it good idea? I am confused

    Please, help me find appropriate solution at Uncle Bob style

    Thanks a lot! 

Todas as Respostas

  • segunda-feira, 6 de agosto de 2012 08:55
     
     
    Someone?
  • quarta-feira, 8 de agosto de 2012 05:15
     
     

    Looks like you have assigned two responsibility to IPhone. 

    1. Creating the body

    2. Creating the connection

    What you can do is separate these two concerns into IBuildPhoneBody and ICreatePhoneConnection.

    Then you can compose the objects implementing these two interfaces. For example,

    class BluetoothPhone

    {

    public BluetoothPhone(IBuildPhoneBody phoneBodyBuilder, ICreatePhoneConnection createConnection)

    {

    //You can have both phonebody builder and connection creator to custom tailor the solution.

    }

    }

    That way even in future coin phone can have internet connectivity when added.

  • quarta-feira, 8 de agosto de 2012 06:02
     
     

    Hello, xeon2k

    Thanks for reply

    "Abstract factory" - it is factory. It can "build" objects, different each from other.

    GOF : "Abstract factory... provide an interface for creating families of related or dependent objects without specifying their concrete classes"

    I think, , it is not violate SRP

  • quarta-feira, 8 de agosto de 2012 08:38
     
     

    In the attempt you made, I see composition. I don't see much need of factory here. You can introduce factory for creating phone body and creating connection component. In which case you will have AbstractBodyFactory and AbstractConnectionFactory

    Checkout the abstract factory pattern

    http://xeon2k.wordpress.com/2010/11/28/abstract-factory-pattern/