Tuesday, August 14, 2018

Multilevel Adapter Pattern

Intro

This post continues my "new pattern ideas" series. I'll describe a special version of the adapter pattern that can guarantee several levels of access to objects. In particular I'll show 3 main levels - read, write and class access.

Motivation

We'll consider a 2-tiered system: 
  1. The top tier consists of object folders. Every folder contains objects of one type
  2. The bottom tier consists of objects themselves
What we need to do is separate access levels to this system. We can have read access, write access and class access at any tier. Read access means getting or reading properties of the folder List, folder or object. Write access means everything from the read level plus being able to add/delete folders to the List, being able to add/delete objects in the folder and write access to the object's properties. Class access implies that the classes for the folder and the object have some additional lower-level detail that can be exposed.

Applicability

Use this pattern when you need to use different access levels to a hierarchy of objects. The hierarchy of access levels is clearly defined with the next level having all the privileges of the previous level plus some privileges of its own.

Structure

In general there could be more complicated models but in this specialized version we'll use the following access levels: read, write, class. We also assume that every next level has all the methods of the previous level plus some method specific to this level. All the objects in the structure need to have the following general type hierarchy:
If read access is required a ReadInterface is returned if a write access is required a WriteInterface is returned. Classes are not public. Class access means there could specific operations within the class that are used only in the class or in the package.
But this is not all. We have 2 tiers: folders and objects. It is very important to make sure that if an outside entity has read access to a folder it must have read access to the objects in this folder. The methods of the read interface like getObject(<parameters>) must return the read interface of the object:
public IReadObject getObject(<parameters>) {
...
}
In accordance with this principle the methods of the write interface must return the write interface of the object:
public IWriteObject getObjectFull(<parameters>) {
...
}

This is the structure for folders:
More tiers can be added with the same principle - read access to a tier means read access to all the lower tiers, write access to a tier means write access to the lower tiers etc. The same level of access down the hierarchy. 
It is like for every access level an adapter is created for the implementation class. 

Participants

Folders - contain objects
Objects - elements that can be accessed
ReadInterface - an interface at any tier that represent read access to the object at this tier
WriteInterface - an interface at any tier that represents write access to the object at this tier
Implementation Class - the class of the element at this tier

Consequences

  1. Consistent access level to the folders and objects. In general it could be more fine-grained like read access here and write access there. But in most cases read access to some object in the hierarchy means read access to the objects below.
  2. Clearly defined interfaces for all access levels, good encapsulation. 

No comments:

Post a Comment