Composition over Inheritance on Android

0 downloads 170 Views 3MB Size Report
Most of the apps has a BaseActivity. Reusing activity codes. Inheritance? In most situations we reuse functionality. Com
Balogh Tamás

Composition over Inheritance on Android

github.com/BaloghTamas/Composition

The theory behind

The problem class TimeLogger { void log (…){...} }

//prints time

class NameLogger { void log (…){...} }

//prints classname

class TimeNameLogger extends TimeLogger,NameLogger { void log (…){...} //should print classname and time in that order }

The theory behind

Inheritance Implementation inheritance • class Some extends Other To achieve code reuse Suitable for IS-A relationship For reusing fields and state Problems • Designed for extension? • Across boundaries? • Class must evolve with the Superclass • Violates encapsulation

The theory behind

Composition ~Delegation Pattern • Delegator class compose a field of the reused class • Often using a list of delegated classes (~ similarities to Strategy Pattern)

Suitable for HAS-A relationship For extending functionality Achieving sort of multiple inheritance Problems • More boilerplate • Delegator class must evolve with composed classes

The theory behind

A possible solution … interface Logger{ void log(…){…}} class TimeLogger implements Logger { void log (…){...} //prints time } class NameLogger implements Logger{ void log (…){...} // prints classname } class TimeNameLogger{ List loggers; void log (…){...} //iterates through loggers and call log }

Composition on Android

Compose Adapters Adapter – Transforms Model item to View item, handles Recycling Delegate the transformation of a model type to an AdapterDelegate interface AdapterDelegate{ ViewHolder onCreateViewHolder (…); void onBindViewHolder (…); int getItemType(); } class DeliveriesAdapter extends BaseAdapter{ List delegates; ViewHolder onCreateViewHolder(…); //finds and calls delegate void onBindViewHolder(…); //finds and calls delegate int getItemType(); //calls the proper delegate }

Composition on Android

Compose Adapters

class ReceiveAdapter implements AdapterDelegate{ ViewHolder onCreateViewHolder(…) {...} void onBindViewHolder(…) {...} int getItemType() {…}

class SendAdapter implements AdapterDelegate{ ViewHolder onCreateViewHolder(…) {...} void onbindViewHolder(…) {...} int getItemType() {…}

Composition on Android

Compose Adapters Example: Delivery Tracking Application • • • •

List with multiple types A screen for things that I receive A screen for things that I send A screen for both

Change Request #1 • Lets add sections/headers to that list • With inheritance

CalendarDeliveryAdapter extends DeliveryAdapter

• With composition

addAdapterDelegate(new HeaderDelegate(…))

Composition on Android

Compose Adapters Change Request #2 • Display Offers just for “Send” screen. • Display Options for picking up your package only for “Receive” screen. • With inheritance OffersAdapter extends CalendarDeliveryAdapter OptionsAdapter extends CalendarDeliveryAdapter

• With composition addAdapterDelegate(new OfferDelegate(…)) addOptionDelegate(new OptionDelegate(…))

Change Request #3 • • • •

Display Offers and Options on overview screen But don’t categorize by date With inheritance - Refactor! With composition – Just add the right delegates

Composition on Android

Compose Activities Extending an Activity Even a “Hello world” requires that

Having base activity classes Most of the apps has a BaseActivity

Reusing activity codes Inheritance? In most situations we reuse functionality

Composition on Android

Compose Activities Utilize Social Libraries High depend on Activity lifecycle Base class: class SocialActivity extends AppCompatActivity MyActivity extends SocialActivity

Utilize ThemeActivity Sets the theme class ThemeActivity extends AppCompatActivity MyActivity extends ThemeActivity

What if an Activity both Social and Themed? Multiple inheritance? Code duplication?

Composition on Android

Compose Activities interface ActivityDelegate{ public void onCreate(…); //... public void onDestroy(…); } abstract class CompositeActivity extends AppCompatActivity{ List delegates public void onCreate(…){...} //iterates through delegates }

//...

and calls ...

Composition on Android

Compose Activities class SocialDelegate implements ActivityDelegate{ public void onCreate(…){...} // Social integration logic } class ThemedDelegate implements ActivityDelegate{ public void onCreate(…){...} // Theme handling logic }

Should provide activity reference for letting delegates access activity Protected fields and methods are not available Can be used for Fragments the same way

Composition on Android

Summary

Inheritance is not always the key for reuse IS-A -> Use inheritance HAS-A -> Use composition Inherit state -> Use inheritance Inherit functionality -> Use composition Multiple inheritance-> Use composition On Android • For flexible Adapter -> Compose Adapters • For multiple Activity/Fragment inheritance -> Compose Activities/Fragments

Composition on Android

References Joshua Bloch – Effective java Hannes Dorfmann - JOE'S GREAT ADAPTER HELL ESCAPE

github.com/BaloghTamas

[email protected]

The future

.. and another possible solution interface Logger { fun log() } interface TimeLogger: Logger { override fun log(){ Log.d("Time", Date().toString())} } interface NameLogger: Logger { override fun log(){ Log.d("Name",javaClass.toString())} } class NameTimeLogger: TimeLogger, NameLogger{ override fun log() { super.log() super.log() } }