简体   繁体   中英

Encapsulate the properties design pattern

I want to encapsulate the logic how a document is activated(boolean). When a document is activated it should be added to a list of activeDocuments and the flag should be set to true. I want to forbid the direct access to the isActive property.

class DocumentService {
      private activeDocuments : Map<DocumentModel> = new Map<DocumentModel>();

      // Activates the document and adds it to the list
      activateDocument(document: DocumentModel) {
                document.setActive();
                activeDocuments.set(document.id, document);
      }
}


class DocumentModel {
      private isActive: boolean;

      setActive() {
                this.isActive = true;
      }         
}

class DocumentComponent {
      documentSelected() {
           // this.document.setActive()  - SHOULD BE FORBIDDEN because the document is not added to the activedocument list !
           this.documentService.activateDocument(this.document);
      }
}

The only solution that i figured out for this problem is to create two interfaces DocumentServiceInterface that has a setActive() method and DocumentInterface that doesn't have it so it prevents the |DocumentComponent to activate the document but the service can still activate the document.

Is there a design pattern/ recipe that can solve this ?

Iterating through the list of documents to check if it's active or not is not an option because the structure is much more complex in the application and the number of documents should scale (for example there could be multiple thousand documents)

you can use Mediator Design Pattern to solve the problem. or if you want to hidden the method to the client code only, you can use es2015 symbol methods,then the code out of your DocumentService & DocumentModel can't access the active method,because the visibility of ACTIVE is only visible in module,the code like as below:

const ACTIVE = Symbol("active");

class DocumentService {
    private activeDocuments: Map<String,DocumentModel> = new Map<String,DocumentModel>();

    // Activates the document and adds it to the list
    activateDocument(document: DocumentModel) {
        document[ACTIVE]();
        this.activeDocuments.set(document.id, document);
    }

}

class DocumentModel {
    public id: string;
    private isActive: boolean;

    [ACTIVE]() {
        this.isActive = true;
    }
}

A javascript specific way to do it would be like:

setActive() {
    if (arguments.callee.caller.toString()!=='DocumentService')
         throw new Exception();
}

but i find it quite unconventional and hard to read

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM