Archive for the 'How to Select Design Pattern' Category

Sandlight CMS III: PHP Abstract Factory

abfacNote: This is the third in a series for developing a CMS for Sandlight Productions. Drop by the Sandlight site to see the progress so far, and be sure to check your country’s flag count!

Now that the CMS has a filter for different devices, it now needs a pattern to take care of those devices and different types of content that they will display. Previous posts on this blog used the Bridge pattern and the Factory Method pattern. However, another pattern might be more useful for all of the different things that a Content Management System (CMS) might do. A review of the series of posts on this blog for how to select a design pattern, shows the different criteria to consider. The CMS has to create different elements of a Web page for different devices and that fact must be the focal point of the consideration. The section head for Creational Patterns in Learning PHP Design Patterns, lists the Abstract Factory pattern as a creational one, but that pattern was not discussed in the book nor on this blog. It would appear to be just what this CMS needs.

The Abstract Factory Design Pattern

The Abstract Factory pattern has features for families of factories and products instead of individual factories as does the Factory Method pattern. In comparing the relatively simple Factory Method pattern with the Abstract Factory, the Abstract Factory has multiple abstract product interfaces with multiple concrete factories for the families of the products.

Figure 1 shows the the Abstract Factory class diagram, and when you look at it, try to focus on the fact that the pattern has two types of interfaces: Factory and Product. So, if you understand the Factory Method pattern, you have a starting point for appreciating the Abstract Factory:

Figure 1: Abstract Factory class diagram

Figure 1: Abstract Factory class diagram

Unlike the Factory Method pattern, the Abstract Factory includes a Client class as an integral part of the pattern. Further, the Client holds an association between both the AbstractFactory (AbsFactory) and the two AbstractProduct classes. So while it shares some of the basic Factory Method characteristics, it is clearly a different pattern than the Factory Method.

Since the Abstract Factory may appear to be daunting, the color-coded the product instantiations (dashed lines) in the file diagram (appearing in the Play window) help show where each concrete factory method calls. Experiment with different combinations of factories (devices) and products (page parts) and look at the diagram so that you can see the path. Phone instantiations are in green, Tablet in red, and Desktop in blue. Experiment with the different single products first, and then click the bottom button to see what different “pages” each device factory displays.

Implementing the Abstract Factory in PHP

To see how this implementation of the Abstract Factory design pattern works, click the Play button. You will see both the interactive Abstract Pattern tester and the of the file diagram of this implementation of the Abstract Factory for the evolving Sandlight CMS. Click the Download button to see all of the files in the diagram. For this particular post, downloading all of the files is more important than usual because there are lots of them, and rather than having listings for all in this write-up, I’ve just selected representative ones.
PlayDownload

In addition to the Abstract Factory file diagram (viewed when you click the Play button), the following quick overview of the participants’ roles and how the CMS implements the Abstract Factory explain how this implementation works:

Client client: Only uses interfaces declared by IAbFactory (interface) and IProducts (abstract classes IHeaderProduct, IImageProduct and ITextProduct.) This means that the Client can only use the classes and methods implemented from those two interface types—factory or products. In other words, it should not directly implement a product (a page element) by directly using a product independent of the factory and product interfaces. Figure 2 illustrates this point:

Figure 2: Client works through Abstract Factory implementations

Figure 2: Client works through Abstract Factory implementations

In going over the other participants below, keep in mind that the Client can only implement concrete implementations of the IAbFactory to request products (page parts for different devices.)

IAbFactory interface: Establishes the methods for the concrete factories.

  • PhoneFactory implements operations to create phone products
  • TabletFactory implements operations to create tablet products
  • DesktopFactory implements operations to create desktop products

IHeaderProduct: abstract class Establishes the method for concrete header products and adds protected property for returning completed product.

  • PhoneHeader defines phone object to be created by the PhoneFactory and
    implements the IHeaderProduct interface
  • TabletHeader defines tablet object to be created by the Tabletactory and
    implements the IHeaderProduct interface
  • DesktopHeader defines desktop object to be created by the DesktopFactory and
    implements the IHeaderProduct interface

IImageProduct: abstract class Establishes the method for concrete image and/or video products and adds protected property for returning completed product.

  • PhoneImage defines phone object to be created by the PhoneFactory and
    implements the IImageProduct interface
  • TabletImage defines tablet object to be created by the Tabletactory and
    implements the IImageProduct interface
  • DesktopImage defines desktop object to be created by the DesktopFactory and
    implements the IImageProduct interface

ITextProduct: abstract class Establishes the method for concrete text products and adds protected property for returning completed product.

  • PhoneText defines phone object to be created by the PhoneFactory and
    implements the ITextProduct interface
  • TabletText defines tablet object to be created by the Tabletactory and
    implements the ITextProduct interface
  • DesktopText defines desktop object to be created by the DesktopFactory and
    implements the ITextProduct interface

Comparing the above outline with the Abstract Factory file diagram (seen when you click the Play button) shows that the Abstract Factory is bound to the idea of a factory implementing a product. The specific classes (products) requested are never directly referenced by the Client; rather it is through a factory. The CMS application requires factories for the different device categories; Phone, Tablet and Desktop. Each factory should be able to build the necessary parts (products) for each device. In this case (and for this example) the products are a Header, Graphic and Text. Each factory can build its own version of the products; so requesting a header, for example, is through a concrete factory, and depending on which concrete factory the clients requests, it builds the appropriate product.
Continue reading ‘Sandlight CMS III: PHP Abstract Factory’

Share

PHP Bridge Pattern CMS

bridgeCMSA Flexible CMS

The previous post on the PHP Bridge Design pattern shows how a Bridge pattern has two connected but independent interfaces to make design flexibility for different online devices. This post explores how that same flexibility extends to making a Content Management System (CMS). Most of the Bridge participants in the design are unchanged or only slightly changed.

The major change in the Bridge design pattern actually makes it more in line with the original intention of the Bridge. The RefinedAbstraction participant (RefinedPage) no longer includes concrete content for the page. Instead, it provides the parameters for a client to add the content. This change adds flexibility and gives the developer more options than the original StandardPage class.

Two UIs and Multiple Clients

In order to make a decent CMS, you need to have at least two UIs:

  1. An Administrative UI for previewing and adding new content
  2. A User UI for viewing but not changing content

In creating the Administrative UI (HTML5/PHP/JavaScript), I had to use two PHP clients. One client is to preview the new data entered by the admin and the other client is to store the new data (after previewing and possibly editing it). Figure I provides a general overview of the UIs and the Clients that will use the Bridge pattern for a CMS:

Figure 1: User Interfaces and Clients

Figure 1: User Interfaces and Clients

The Administrative UI (BridgeCMSAdmin.html) uses the BridgeCMSAdminClient class for displaying different content and the StoreDataClient class for storing the information in a JSON file. An important condition to remember is that when using JSON files, you need to make their permissions available for reading and writing. (See the Memento II post and the special mini-post on setting permissions on Raspberry Pi systems.) Thus, the need for two clients; one for previewing new material and another for storing it in a JSON file. A lot of files are involved in this CMS; so take a look at the two different UIs and download the files for everything:
PlayPlayAdminDownload

To use the Administrator Module, follow these steps in the listed order:

  1. Type in Header data, select a graphic from the drop down menu, and then type in text for the body.
  2. Click a Desktop, Tablet or Phone radio button and then click Preview Page
  3. When you have everything the way you want it, First click Transfer to Storage and next click Store Data
  4. Now click the Play button and see the page you created.

In the admin UI, I used a drop down menu with only three selections for the graphic file since only three were set up. However, it would not be difficult to upload graphics and their file names. (See the post on uploading graphics using the Template Method.)

The UIs and their Clients

The main feature in creating a CMS is the Administrative UI. It calls two different clients for dealing with previews and persistent data storage. Unless you’re planning on a fairly long body text entry, the JSON file works fine. Look at the code below, and you can see that one of the issues is that the data that is entered for the preview must be transferred to a different form. It transferring the data is a simple task with a little JavaScript. The following script is all it takes:

?View Code JAVASCRIPT
function transferData(formNow)
{
    formNow.header.value = bridgeWork.header.value;
    formNow.graphic.value = bridgeWork.graphic.value;
    formNow.bodytext.value = bridgeWork.bodytext.value;
}

Stored in an external JS file, it was used only when the data was going to be stored; however, before storing it, it had to be transferred from the bridgeWork form to the dataStore form.

< !DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" type="text/css" href="cmsbridge.css"/>
    <script src="formXfer.js"> </script>
    <title>CMS Admin Bridge</title>
</head>
<body>
    <h2>Enter Update Data</h2>
    <form method="post" name="bridgeWork" action="BridgeCMSAdminClient.php">
        <input type="text" name="header"/>&nbsp;Header<br />
        <select name="graphic">
            <option>Select Travel Graphic</option>
            <option value="nephpAir.jpg">Air</option>
            <option value="nephpTrain.jpg">Train</option>
            <option value="nephpShip.jpg">Ship</option>
        </select>
        <br />
        Enter the text for the body below:<br />
        <textarea name="bodytext" cols="48" rows="12"></textarea><p></p>
        <h3>Preview New Data</h3>
        <input type="radio" name="device" value="Desktop"/>&nbsp;Desktop<br />
        <input type="radio" name="device" value="Tablet"/>&nbsp;Tablet<br />
        <input type="radio" name="device" value="Phone"/>&nbsp;Phone<p></p>
        <input type="submit" name="deliver" value="Preview Page"/>
    </form>
 
    <h3>Store New Data</h3>
    <form method="post" name="dataStore" action="StoreDataClient.php">
        <input type="hidden" name="header"/>
        <input type="hidden" name="graphic"/>
        <input type="hidden" name="bodytext"/>
        <button type="button" onclick="transferData(dataStore)">Transfer to Storage</button>
        <input type="submit" name="jsonstore" value="Store Data"/>
    </form>
 
</body>
</html>

Then using build-in PHP JSON json_encode() method, the data were placed into an array and stored in the JSON file. This was done using the StoreDataClient class:

< ?php
class StoreDataClient
{
    private static $dataStorage=array();
    private static $jsonFile="content.json";
    //Client stores data
    public static function store()
    {
        if (isset($_POST['jsonstore']))
        {   
            self::setStore();
        }
      file_put_contents(self::$jsonFile,json_encode(self::$dataStorage,JSON_UNESCAPED_UNICODE));
    }
 
    private static function setStore()
    {
        //Pushes data from HTML to array
        array_push(self::$dataStorage,$_POST['header'],$_POST['graphic'],$_POST['bodytext']);
    }
}
StoreDataClient::store();
?>

Just in case you’re wondering why a single PHP client class was not used for both preview and storage, it’s simple:

OOP Principle: Each class should have only a single responsibility.

We don’t want to cram classes; so each responsibility has its own class. (Click below to see the other client and the rest of the CMS.)
Continue reading ‘PHP Bridge Pattern CMS’

Share

Choosing a PHP Design Pattern: Part III —Intentions & Encapsulating Variation

PickDP3I was very sorry when I found out that your intentions were good and not what I supposed they were.Sitting Bull after the Battle of Little Big Horn

Easing into a Selection

We have a bumper crop of peaches this year, and I’ve been peeling, slicing and freezing peaches for the last couple of weeks. It reminded me that Part III of Choosing a PHP Design Pattern is due. This is the third and last installment in the series. You might want to take a look at Part I and/or Part II of this series before or after looking at this post.

Wouldn’t it be nice if you could type in the name of your intended project and up pops the best possible design pattern for that project? Even if you hold your breath until you turn blue, that’s not going to happen. However, such a project (a DP Picker) is a worthy one. You can begin to narrow down your choices by asking whether your project is one that belongs in the Creational, Structural or Behavioral categories. If you’re lucky, you’ll end up with the Creational category and only have five patterns from which to choose. (Since the Singleton is one of that group, you really only have to choose from four.) The following is a summary of each category. (The major sections of Learning PHP Design Patterns begin with a brief overview of each category. See pages 77, 121 and 167.)

  • Choose Creational When…You want to abstract the instantiation process and separate the use of the object from its creation.
  • Choose Structural When…You want to create larger structures from classes and objects.
  • Choose Behavioral When…You must focus of the communication between objects and the interaction between those objects.

Suppose I want to make an app that spends a lot of time loading and unloading different types of data and/or objects—which is something I often do. I’d probably want to choose a Creational pattern because I’m instantiating and removing lots of objects. Never mind which one; that’ll come later, but I’ve certainly narrowed my choices. On the other hand, if my main focus is going to be a game program, I’m going to need a good deal of inter-object communication and interaction and so I’m going to be looking at the Behavioral patterns. That will leave me with about half of the 24 patterns, but it’s a start.

Attention to Intention

The 24 different patterns have 24 different intentions (The Adapter pattern is counted twice since it has both Class and Object versions). The Gang of Four advise us to study the intention of each pattern to help make a decision about which one to use. Rather than listing them here, you can use the table developed in an earlier post, Design Pattern Variation and Intents Table, where you can also download the code for the table. Click the Play button to see the table:
Play

So what is an intention? Let’s take a look at the Proxy intention to get an idea:

Proxy Intention: Provide a surrogate or placeholder for another object to control access to it.

That kind of intention is pretty easy to envision. A login is one example where the user is logging into the Proxy and not the Real object. This was shown in Chapter 11 of Learning PHP Design Patterns and in a post on the Proxy pattern on this blog. (Click below to continue.)
Continue reading ‘Choosing a PHP Design Pattern: Part III —Intentions & Encapsulating Variation’

Share

Choosing a PHP Design Pattern: Part II—Avoiding Redesign

PickDP2What are the causes of System Redesign?

To get started on Part 2 of choosing a design pattern, we need to look at the causes of redesign. I realize that his is jumping ahead in the list, but because the issue of re-design is at the heart of design patterns, it’s a good place for the second discussion of choosing a design pattern. The Gang of Four point out eight causes, and these causes each have design patterns that will help you avoid this redesign (see pp. 23-25 in GoF.) In this session, we’ll review the eight causes and the suggested patterns that can be used to avoid redesign. Look for the cause of redesign that best fits your system or general type of app.

Creating an object by Specifying a Class Explicitly

In one sense, this cause for redesign can be handled by the what you might do in making a movie deal–

Talk to my agent…

You don’t want to deal with the lawyers, contracts and all the negotiations required to make a movie deal. You just want to read the script, rehearse and get your lines straight. You let Murray (your agent) do all of that for you so you don’t get all tangled up with details you don’t know about or want to know about. Right away, you may be thinking,

That sounds like a Factory…

That’s right! You let the factory deal with the class your client wants to make a request from. A Proxy or Prototype would be another choice for separating request from the class you’re making the request to.

Dependence on specific Operations

Another cause for re-design is a dependence on specific operations which may change. The reason for changing an operation or a set of operations can be anything from a bright idea you get for a better way to set up the operations to changes in the objects the used by the operations. It could also be due to a new operation you want to add to the system. Suppose your system has an operation that handles the request for a phone number. The number could be anything from a land-line phone to a Skype number or something in the future none of us have even though of. You don’t want change in or the addition of a single operation to cause re-design for the whole site. So avoid hard-coded requests and let the decisions be made at compile time or run time. Two examples that avoid tightly bound requests are the Chain of Responsibility and Command patterns.

Dependence on Hardware and Software platforms

If you’re programming on a fairly low level, hardware differences can be more pronounced because you can program directly to the processor. PHP is a server-side language sent to a browser and it doesn’t matter is the user’s system is Linux, Windows and Mac operating systems. So platform is not something we tend to worry about or even have to concern ourselves with—albeit a few exceptions.

Having written design patterns for PHP5+, ActionScript 3.0 and a little Java, I am able to preserve most structures in a cross-language environment. However, I do need to attend to language differences, such as the fact that PHP5+ is weakly typed and ActionScript 3.0 is strongly typed. Gamma and associates suggest the Abstract Factory and Bridge designs to help overcome any software dependencies that may arise. The high level abstraction in both patterns helps to ameliorate any differences in hardware and software. However, most design patterns encourage communication between interfaces rather than concrete implementations, and so I would suggest that most (if not all) design patterns have a healthy regard for cross-platform and cross-API cases.

Dependence on Object Representations or Implementations

<em><strong>Figure 1:</strong>Works like Bait & Switch—as long as the interface is the same, it can make the request</em>

Figure 1: Works like Bait & Switch—as long as the interface is the same, it can make the request

We assume when we build a client class that it will simply make requests. However, to make those requests it has to know how an object is represented, stored, located, and implemented. Rather than having that responsibility thrust upon the client, GoF suggest hiding that information from the client. Then if changes are made, the client can make the same request and the information will be handled through abstract structures where change will not ripple through to the client nor the program. Figure 1 suggests that the Client doesn’t know what it’s getting itself into, and in this case, that’s a good thing! The Abstract Factory and Bridge designs along with Memento and Proxy designs keep request processing information hidden from the client, and so when changes are made, the client can make the same requests but get different implementations representing any changes to the system.
Continue reading ‘Choosing a PHP Design Pattern: Part II—Avoiding Redesign’

Share