Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 17. Applying Patterns to Design a Persistence Framework

Similar presentations


Presentation on theme: "Chapter 17. Applying Patterns to Design a Persistence Framework"— Presentation transcript:

1 Chapter 17. Applying Patterns to Design a Persistence Framework

2 Key Takeaway Points A persistence framework hides the database access functions from business objects. It substantially reduces the impact to the business objects when the database is changed. The persistence framework applies the bridge, command, factory method, prototype, proxy, and template method patterns.

3 Process for Applying Patterns

4 Pattern Application Process
Perform design as usual. Perform design activities as described in Chapters 9 through 15. Continue with Step 2 if a design problem is encountered. Search for patterns to solve design problem. Look up patterns in Figure 16.2 of textbook. Apply selected patterns. Match pattern classes with design classes, introduce remaining pattern classes into existing design Review to ensure correctness.

5 Motivating Example: Consider This Design
:Checkout GUI :Checkout Controller <<retrieve patron info and document info>> <<uid, cnList>> msg:=checkout (uid, cnList): String <<patron info and document info>> <<msg>> msg:=processCheckout(): String <<update db>> What is “wrong” with it?

6 Problems with the Design
The controller has to know how to work with a database. The controller may also need to know the business logic. Since every controller works with a database, much database access code is duplicated. If a different type of database is used, the controller has to be changed. If the database is on a remote machine, the controller also has to implement network protocols. If the needed information is distributed over several databases, the controller has to work with all of the databases.

7 Applying Separation of Concerns
Separation of concerns is a software design principle (Edsger W. Dijkstra). Separate database concerns from the business logic concerns. The database concerns are separated and delegated to another object (class) – the database manager.

8 Delegate DB Concerns to a DB Manager
:Checkout Controller :DBMgr l:Loan b: Book <<JDBC/ODBC>> msg:=checkout (uid, cnList): String u:=getUser(uid): User RDB [u!=null & cn in cnList]*: process(cn) b:=getBook (cn): Book a:=isAvailable() [a] create(u,d) [a] saveLoan(l) [a] setAvailable(false) [a] saveBook(b)

9 It hides the database from the controller.
Database Manager It hides the database from the controller. It is a bridge between the controller and the database. It constructs the business objects from database records. DB manager design considerations: What if the database is at a remote site? What if the DBMS is changed from SQL to Oracle? What if multiple databases are used?

10 Applying Bridge Pattern
DB Access Impl DBMgr getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) Italic means abstract or interface. impl Dash line means implements. imp.saveBook(book) LDAP Access Oracle Access SQL Access getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ...

11 Bridge Pattern Sample Code
interface DBAccessImpl { public User getUser(String uid); public Book getBook(String callNo); public void saveLoan(Loan loan); public void saveBook(Book book); } This is equivalent to pure virtual methods in C++. public class LDAPAccess implements DBAccessImpl { public User getUser(String uid) { /** get a User object from the LDAP DB*/ } public Book getBook (String callNo) { /** get a Book object from the LDAP DB */ } public void saveLoan(Loan loan) { /** save a Loan object to the LDAP DB */ } public void saveBook(Book book) { /** save a Book object to the LDAP DB */ } } Oracle Access and SQL Access are implemented similarly.

12 Bridge Pattern Sample Code
One way to change the DB access dynamically. DBMgr public class DBMgr { DBAccessImpl imp; public DBMgr() { ... imp=Config.getInstance(). getDB(); } public User getUser (String uid) { return imp.getUser (uid); } public Book getBook (String callNo) { return imp.getBook (callNo); } public void saveLoan (Loan loan) { imp.saveLoan (loan); } public void saveBook (Book book) { imp.saveBook (book); } getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) return imp.getUser(uid); impl DB Access Impl getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... LDAP Access Oracle Access SQL Access getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ...

13 Bridge Pattern Sample Code
:Checkout Controller public class CheckoutController { DBmgr dbm=new DBMgr(); ... public String checkout (String uid, String cn) { User u=dbm.getUser(); if (u!=null) return process(cn, u); } public String process (String cn, User u) { Document d=dbm.getBook(cn); if (d.isAvailable()) { Loan l=new Loan (u, d); dbm.saveLoan(l); d.setAvailable(false); dbm.saveBook(b); :DBMgr msg:=checkout (uid, cn): String u:=getUser(uid): User [u!=null] msg:=process(cn, u): String b:=getBook(cn): Book to Book a:=isAvailable() to Loan [a]create(u,b) [a]saveLoan(l) to Book [a]setAvailable(false) [a]saveBook(b)

14 The Bridge Pattern Decouples the client interface from its implementation. Lets the client interface and implementation change independently. Hides the implementation details from the client – it does not know which implementation it is using. Often used to design systems that require the flexibility to change the client interface or implementation dynamically.

15 Potential Problems DBMgr DB Access Impl getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... impl If DBMgr has many functions, then each concrete DB access class will have thousands of lines of code. LDAP Access Oracle Access getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ...

16 Applying Command Pattern
SQL Access executes a query to save the book to the database. Return null. delegate getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) SQLCmd execute():Object SaveBook sb=new SaveBook(book); sb.execute(); GetUser execute(): Object GetUser(uid: String) GetBook GetBook(cn: String) execute(): Object SaveLoan execute(): Object SaveLoan (Loan l) SaveBook execute(): Object SaveBook (b:Book) this.book=book; Define a Command Interface SQL Cmd that contains an execute(): Object method. For each client operation, implement a concrete command class that realizes the client operation. Each client operation delegates the work to the corresponding concrete command.

17 Supporting Undo and Redo
To support undo and redo extend the command interface with following abstract operations, implemented by the command subclasses undo() redo() reversible():boolean, returns true if command is reversible maintain a history of executed commands each command stores the information needed to undo the command past present undo redo

18 Benefits of Command Pattern
Each command object encapsulates an operation or request. The command pattern defines a uniform interface for executing different operations. It decouples the client from the command objects. It is easy to introduce new command subclasses. Commands can be queued and executed at a later time. It supports undo and redo operations. Commands can be composed to form composite commands using the composite pattern.

19 Share Common Code Among Subclasses
SQLCmd execute():Object GetUser GetUser(uid: String) execute(): Object connectDB(); makeQuery(); executeQuery(); disconnectDB(); processResult(); return result; Steps that are common. GetBook GetBook(cn: String) execute(): Object Steps that are different. SaveLoan execute(): Object SaveLoan (Loan l) execute(): Object SaveBook (b:Book) SaveBook

20 Applying Template Method
SQL Cmd connectDB(); makeQuery(); executeQuery(); disconnectDB(); processResult(); return result; Steps that are common. Steps that are different. reused by the subclasses execute(): Object makeQuery() processResult() connectDB() executeQuery() disconnectDB() hook methods GetBook SaveLoan GetUser SaveBook GetUser(uid: String) makeQuery() processResult() GetBook(cn: String) makeQuery() processResult() SaveLoan (Loan l) makeQuery() processResult() SaveBook (b:Book) makeQuery() processResult() query=“select * from UserTable where UserTable.uid=\””+uid+”\””; query= “insert into LoanTable (...)”;

21 Template Method Pattern
Skeleton code in which the abstract hook methods are invoked. AbstractClass templateMethod() hookMethod1() hookMethod2() Concrete1 hookMethod1() hookMethod2() Concrete2 hookMethod1() hookMethod2() Concrete subclasses implement the hook methods to provide varying behaviors.

22 Benefits of Template Method
It defines the code skeleton with hook methods to provide varying behaviors implemented by subclasses. It can be used to extract common code from the subclasses into a template method of the parent class to facilitate maintenance. It reduces the effort required to implement the subclasses. Variation: The parent class may provide default implementations for the hook methods.

23 The Result Is the Factory Method Pattern
Template Method The Result Is the Factory Method Pattern : Product ... Product p=hookMethod2(); Factory method AbstractClass templateMethod() hookMethod1() hookMethod2() Product Product 1 Product 2 Concrete1 Concrete2 hookMethod1() hookMethod2() hookMethod1() hookMethod2() : Product return new Product1(); : Product return new Product2(); Factory method is a special case of template method –template method applied to object creation.

24 DBMgr Design: Accessing a Remote Database
DB Access Impl getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... impl One or more databases may be at a remote location. The concrete DB access implementations may need to implement network communication. LDAP Access Oracle Access SQL Access getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) ...

25 Applying Remote Proxy DBMgr DB Access Impl Net Interface
openSocket(...) closeSocket(...) ... imp getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) SQL Access Proxy Remote SQL Access network getUser(uid):User getBook(callNo): Book saveLoan(loan) saveBook(book) openSocket(...) closeSocket(...) ... getUser(uid):User getBook(callNo):Book saveLoan(loan) saveBook(book) openSocket(...) closeSocket(...) ... Use TCP/IP, Java RMI, or CORBA to call the remote object. Remote SQL DB

26 Using the Remote Proxy :Checkout Controller :DBMgr l:Loan b:Book
:SQL Access Proxy u:=get User(uid) u:=getUser(uid) u:=getUser(uid) [u!=null & cn in cnList]*: process(cn) b:=getBook(cn) b:=getBook(cn) a:=isAvailable() [a]create(u,d) [a]save(l) save(l) [a]setAvailable(false) [a]save(d)

27 Using the Remote Proxy (continued)
:SQL Access Proxy s:Socket s:=openSocket() u:=getUser(uid) sendQuery() receive() closeSocket() u:=construct User()

28 Proxy Pattern Problems solved: Solution:
Accessing a remote object is not desired or not possible. Providing a placeholder for an expensive object. Controlling access to an object to implement access rights. Solution: Add a level of indirection with a proxy that implements the same interface as the real object. The proxy controls and enhances the access to the real object. Interface operation () operation () Real Object operation () Proxy subject delegate to Implements additional functionality in addition to calling subject.operation().

29 Types of Proxy Remote proxy: providing a local presence for an object in a different address space: Example: a remote database Using Java RMI (Remote Method Invocation) CORBA (Common Object Request Broker Architecture) Virtual proxy: acting as a placeholder for an expensive object to be created later Protection proxy: controlling access to another object according to access rights Smart reference proxy: performing additional actions when the original object is accessed

30 Applying Remote Proxy The stub and skeleton used to communicate between remote objects are proxies. Client Remote Object Stub service() Remote Object Skeleton service() Remote Object service()

31 Virtual Proxy and Example
Common Interface request() The real object is memory intensive, or expensive to create. if (real==null) { create real; real.request(); } Proxy request() Real Object request() Client real Graphics g=new ImgProxy(); ... g.draw(); Image imgImp draw() load(const char*) Client Graphics ImgProxy fileName img if (img==null) { img=new Image(); img.load (fileName); } img.draw();

32 Smart Reference Proxies
Smart pointers automatically count number of references to the real object so that the memory can be free when no reference exists keep track of which attributes of an object has been updated to improve DB operation efficiency Loading a persistent object into the memory when it is first referenced Checking that a shared object is locked before access

33 Responsibilities of a Proxy
Controls access to the real object. May create or delete the real object. Encodes a request and communicates with the remote object. Delays access to the real object until it is needed. Checks the right to access a real object.

34 Benefits of The Proxy Pattern
Usefulness of the different types of proxy Provide copy-on-write capability storing a copy of a large complex object only when modification has been made to the object

35 How to Reduce Number of Classes
Car Do different cars have different behavior and different relationships? housepower numOfSeats milesPerGallon If not, then only one class is sufficient. ... Toyota Santana Ford Edge Granada Camry Corolla

36 Prototype Pattern <<Singleton>> get prototype ProtoMgr
get(key):Object add(key, Object) remove(key) maintain Client operation() prototype * Prototype ProtoMgr pm = ProtoMgr.getInstance(); Prototype p=pm.get(“Ford Edge”); if (p==null) { Car edge=new Car(); edge.setMake(“Ford”); edge.setModel(“Edge”); ... pm.add(“Ford Edge”, edge); p=pm.get(“Ford Edge”); } Car c=(Car)p.clone(); c.setX(...); ... clone():Object * Car Document make model housepower numOfSeasts milesPerGallon type callNumber author title clone():Object ... ... clone():Object ...

37 Object Interaction in Prototype
:TypeK client: :ProtoMgr prototype: c:Car c:=(Car)get(“Ford Edge”) c:=get(“Ford Edge”) setX(...) foo()

38 Prototype Pattern Benefits Reducing the number of classes
Easy to add/remove prototypes at run time Improving complex object creation efficiency Support dynamically loaded classes (DLC) DLC cannot be referenced at compile time. The class loader creates and registers an instance of the DLC at run time when the DLC is loaded As an alternative to abstract factory – avoiding the factory hierarchy parallel to the product hierarchy

39 The Prototype Pattern Liabilities
Each subclass of Prototype must implement the clone operation deep copy if copy and original must be independent shallow copy is sufficient otherwise Implementing clone may be difficult if the component objects do not support cloning, or there are circular references

40 Class Exercise What are the design objectives of singleton, flyweight, and prototype? What are the similarities and differences between prototype and flyweight? In the persistence framework, can prototype be applied to reduce the number of command classes? Can prototype be applied to eliminate an Abstract Factory?

41 Persistence Framework: Putting It Together
bridge remote proxy Controller DBMgr DB Access Interface Net Interface getX(): X saveX(x:X) getX(): X saveX(x:X) openSocket() closeSocket() calls hook1() and hook2() command, template method and factory method DBX Cmd DBX Access DBY Proxy Remote DBY execute(): Object hook1() hook2(): Object getX(): X saveX(x:X) getX(): X saveX(x:X) openSocket() closeSocket() getX(): X saveX(x:X) openSocket() closeSocket() Get X Save X GetX(...) hook1() hook2(): Object SaveX(...) hook1() hook2(): Object

42 Class Discussion What are the differences and similarities between Adapter and Proxy? When to use Adapter and when to use Proxy?

43 Applying Agile Principles
Same as in Chapter 16.


Download ppt "Chapter 17. Applying Patterns to Design a Persistence Framework"

Similar presentations


Ads by Google