├── .gitignore
├── LICENSE
├── README.md
├── config.json
├── gulpfile.js
├── index.html
├── karma.conf.js
├── karma_sourcemaps.js
├── package.json
├── src
├── abstract_factory
│ ├── README.md
│ ├── abstractFactory.ats
│ ├── index.html
│ └── runner.ats
├── adapter
│ ├── README.md
│ ├── adapter.ats
│ ├── index.html
│ └── runner.ats
├── bridge
│ ├── README.md
│ ├── bridge.ats
│ ├── index.html
│ └── runner.ats
├── builder
│ ├── README.md
│ ├── builder.ats
│ ├── index.html
│ └── runner.ats
├── command
│ ├── README.md
│ ├── command.ats
│ ├── index.html
│ └── runner.ats
├── composite
│ ├── README.md
│ ├── composite.ats
│ ├── index.html
│ └── runner.ats
├── decorator
│ ├── README.md
│ ├── decorator.ats
│ ├── index.html
│ └── runner.ats
├── facade
│ ├── README.md
│ ├── facade.ats
│ ├── index.html
│ └── runner.ats
├── factory_method
│ ├── README.md
│ ├── factorymethod.ats
│ ├── index.html
│ └── runner.ats
├── iterator
│ ├── README.md
│ ├── index.html
│ ├── iterator.ats
│ └── runner.ats
├── lang.ats
├── logger.ats
├── main.ats
├── memento
│ ├── README.md
│ ├── index.html
│ ├── memento.ats
│ └── runner.ats
├── mvc
│ ├── README.md
│ ├── index.html
│ ├── mvc.ats
│ └── runner.ats
├── observer
│ ├── README.md
│ ├── index.html
│ ├── observer.ats
│ └── runner.ats
├── prototype
│ ├── README.md
│ ├── index.html
│ ├── prototype.ats
│ └── runner.ats
├── proxy
│ ├── README.md
│ ├── index.html
│ ├── proxy.ats
│ └── runner.ats
├── publish_subscribe
│ ├── README.md
│ ├── index.html
│ ├── pubsub.ats
│ └── runner.ats
├── strategy
│ ├── README.md
│ ├── index.html
│ ├── runner.ats
│ └── strategy.ats
├── template
│ ├── README.md
│ ├── index.html
│ ├── runner.ats
│ └── template.ats
└── visitor
│ ├── README.md
│ ├── index.html
│ ├── runner.ats
│ └── visitor.ats
├── wait_for_watcher.js
└── webstorm_traceur.js
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /build
3 | .idea
4 | /out
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Ziya SARIKAYA
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Design Patterns and Idioms in ES6
2 | A collection of design patterns and idioms in ES6
3 |
4 | **Boilerplate forked from [angular/atscript-playground](https://github.com/angular/atscript-playground)**
5 |
6 | ### Initial setup
7 |
8 | ```bash
9 | # Clone the repo...
10 | git clone https://github.com/ziyasal/design-patterns-in-es6.git
11 | cd design-patterns-in-es6
12 |
13 | # Then, you need to install all the dependencies...
14 | npm install
15 |
16 | # If you want to be able to use global commands `karma` and `gulp`...
17 | npm install -g karma-cli gulp
18 | ```
19 |
20 | ```bash
21 | # Do initial build, start a webserver and re-build on every file change...
22 | gulp build serve watch
23 | ```
24 | Open a browser and see the result.
25 |
26 | Current Patterns
27 | ======================
28 |
29 | | Pattern | Description |
30 | |:-------:| ----------- |
31 | | [abstract_factory](src/abstract_factory/abstractFactory.ats) | use a generic function with specific factories |
32 | | [adapter](src/adapter/adapter.ats) | adapt one interface to another using a whitelist |
33 | | 3-tier | data<->business logic<->presentation separation (strict relationships) |
34 | | borg | a singleton with shared-state among instances |
35 | | [bridge](src/bridge/bridge.ats) | a client-provider middleman to soften interface changes |
36 | | [builder](src/builder/builder.ats) | call many little discrete methods rather than having a huge number of constructor parameters |
37 | | catalog | general methods will call different specialized methods based on construction parameter |
38 | | chain | apply a chain of successive handlers to try and process the data |
39 | | [command](src/command/command.ats) | bundle a command and arguments to call later |
40 | | [composite](src/composite/composite.ats) | encapsulate and provide access to a number of different objects |
41 | | [decorator](src/decorator/decorator.ats) | wrap functionality with other functionality in order to affect outputs |
42 | | [facade](src/facade/facade.ats) | use one class as an API to a number of others |
43 | | [factory_method](src/factory_method/factorymethod.ats) | delegate a specialized function/method to create instances |
44 | | flyweight | transparently reuse existing instances of objects with similar/identical state |
45 | | graph_search | (graphing algorithms, not design patterns) |
46 | | mediator | an object that knows how to connect other objects and act as a proxy |
47 | | [memento](src/memento/memento.ats) | generate an opaque token that can be used to go back to a previous state |
48 | | [mvc](src/mvc/mvc.ats) | model<->view<->controller (non-strict relationships) |
49 | | [observer](src/observer/observer.ats) | provide a callback for notification of events/changes to data |
50 | | pool | preinstantiate and maintain a group of instances of the same type |
51 | | [prototype](src/prototype/prototype.ats) | use a factory and clones of a prototype for new instances (if instantiation is expensive) |
52 | | [proxy](src/proxy/proxy.ats) | an object funnels operations to something else |
53 | | [publish_subscribe](src/publish_subscribe/pubsub.ats) | a source syndicates events/data to 0+ registered listeners |
54 | | state | logic is org'd into a discrete number of potential states and the next state that can be transitioned to |
55 | | [strategy](src/strategy/strategy.ats) | selectable operations over the same data |
56 | | [template](src/template/template.ats) | an object imposes a structure but takes pluggable components |
57 | | [visitor](src/visitor/visitor.ats)| invoke a callback for all items of a collection |
58 | | chaining_method | continue callback next object method |
59 | | [iterator](src/iterator/iterator.ats) | Provide a way to access the elements of an aggregate object sequentially |
60 |
61 |
62 | ### What are all the pieces involved?
63 |
64 | #### [Traceur]
65 | Transpiles AtScript code into regular ES5 (today's JavaScript) so that it can be run in a current browser.
66 |
67 | #### [RequireJS]
68 | Traceur is configured to transpile AtScript modules into AMD syntax and we use RequireJS to load the code in the browser.
69 |
70 | #### [Assert] library
71 | When `typeAssertions: true` option is used, Traceur generates run-time type assertions such as `assert.type(x, Object)`. The assert library does the actual run-time check. Of course, you can use your own assert library.
72 |
73 | The idea with type assertions is that you only use them during the development/testing and when deploying, you use `typeAssertions: false`.
74 |
75 | #### [Karma]
76 | Test runner that runs the tests in specified browsers, every time that you change a file.
77 |
78 | #### [Gulp]
79 | Task runner to make defining and running the tasks simpler.
80 |
81 |
82 | [AtScript]: http://atscript.org
83 | [Traceur]: https://github.com/google/traceur-compiler
84 | [RequireJS]: http://requirejs.org
85 | [Assert]: https://github.com/angular/assert
86 | [Karma]: http://karma-runner.github.io/
87 | [Gulp]: http://gulpjs.com
88 |
--------------------------------------------------------------------------------
/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "traceur": {
3 | "modules": "amd",
4 | "script": false,
5 | "types": true,
6 | "typeAssertions": true,
7 | "typeAssertionModule": "assert",
8 | "annotations": true,
9 | "sourceMaps": "file"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var traceur = require('gulp-traceur');
3 | var connect = require('gulp-connect');
4 | var rename_ = require('gulp-rename');
5 |
6 | var TRACEUR_OPTIONS = require('./config').traceur;
7 | var PATH = {
8 | BUILD: './build/',
9 | SRC: './src/**/*.ats'
10 | };
11 |
12 | // A wrapper around gulp-rename to support `dirnamePrefix`.
13 | function rename(obj) {
14 | return rename_(function(parsedPath) {
15 | return {
16 | extname: obj.extname || parsedPath.extname,
17 | dirname: (obj.dirnamePrefix || '') + parsedPath.dirname,
18 | basename: parsedPath.basename
19 | };
20 | });
21 | }
22 |
23 |
24 | // TRANSPILE AT SCRIPT
25 | gulp.task('build/src', function() {
26 | gulp.src(PATH.SRC, {base: '.'})
27 | // Rename before Traceur, so that Traceur has the knowledge of both input and output paths.
28 | .pipe(rename({extname: '.js', dirnamePrefix: PATH.BUILD}))
29 | .pipe(traceur(TRACEUR_OPTIONS))
30 | .pipe(gulp.dest('.'));
31 | });
32 |
33 | gulp.task('build', ['build/src']);
34 |
35 | // WATCH FILES FOR CHANGES
36 | gulp.task('watch', function() {
37 | gulp.watch(PATH.SRC, ['build']);
38 | });
39 |
40 |
41 | // WEB SERVER
42 | gulp.task('serve', function() {
43 | connect.server({
44 | root: [__dirname],
45 | port: 8000,
46 | livereload: false
47 | });
48 | });
49 |
50 |
51 | gulp.task('default', ['serve', 'watch']);
52 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Design Patterns in AtScript
4 |
5 |
6 |
7 | Design Patterns in AtScript
8 |
65 |
66 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Fri Mar 14 2014 15:01:19 GMT-0700 (PDT)
3 |
4 | var traceurOptions = require('./config').traceur;
5 |
6 | module.exports = function(config) {
7 |
8 | var isWebstorm = /karma-intellij/.test(process.argv[1]);
9 | var files;
10 |
11 | if (isWebstorm) {
12 | // Running within WebStorm - WebStorm takes care of transpiling.
13 | // Serve already transpiled files, including source maps.
14 | files = [
15 | {pattern: 'build/src/**/*.js', included: false},
16 | {pattern: 'build/test/**/*.js', included: false},
17 | {pattern: 'build/src/**/*.map', included: false},
18 | {pattern: 'build/test/**/*.map', included: false}
19 | ];
20 | } else {
21 | // Running outside WebStorm (eg. from commandline).
22 | // Karma transpiles the *.ats sources with karma-traceur-preprocessor.
23 | files = [
24 | {pattern: 'src/**/*.ats', included: false},
25 | {pattern: 'test/**/*.ats', included: false}
26 | ];
27 | }
28 |
29 | config.set({
30 | frameworks: ['jasmine', 'requirejs', 'traceur', 'sourcemaps'],
31 |
32 | files: [
33 | // The entry point that dynamically imports all the specs.
34 | {pattern: 'test/main.js', included: true},
35 |
36 | // The runtime assertion library.
37 | {pattern: 'node_modules/rtts-assert/dist/amd/assert.js', included: false}
38 | ].concat(files),
39 |
40 | preprocessors: {
41 | '**/*.ats': ['traceur']
42 | },
43 |
44 | browsers: ['Chrome'],
45 |
46 | traceurPreprocessor: {
47 | options: traceurOptions,
48 | transformPath: function(path) {
49 | // Traceur preprocessor is only used when running Karma outside of WebStorm.
50 | // We change the path to `build/**` so that the paths are the same as with WebStorm.
51 | return path.replace(config.basePath, config.basePath + '/build')
52 | .replace(/\.ats$/, '.js');
53 | }
54 | }
55 | });
56 |
57 | config.plugins.push(require('./karma_sourcemaps'));
58 | };
59 |
--------------------------------------------------------------------------------
/karma_sourcemaps.js:
--------------------------------------------------------------------------------
1 | var SOURCE_MAP = /\.map$/;
2 |
3 | function findFile(files, path) {
4 | for (var i = 0, ii = files.length; i < ii; i++) {
5 | if (files[i].path === path) {
6 | return files[i];
7 | }
8 | }
9 |
10 | return null;
11 | }
12 |
13 | function createSourceMapsPlugin(emitter, basePath, logger) {
14 | var log = logger.create('sourcemaps');
15 |
16 | emitter.on('file_list_modified', function(filesPromise) {
17 | filesPromise.then(function(files) {
18 | files.served.forEach(function(file) {
19 | if (SOURCE_MAP.test(file.path)) {
20 | var sourceMap = JSON.parse(file.content);
21 |
22 | if (!sourceMap) {
23 | log.warn('Invalid source map file', file.originalPath);
24 | return;
25 | }
26 |
27 | var sourceFile = findFile(files.served, basePath + '/' + sourceMap.file);
28 |
29 | if (!sourceFile) {
30 | log.warn('Can not find source file for map', file.originalPath);
31 | return
32 | }
33 |
34 | sourceMap.sourceRoot = basePath;
35 | sourceFile.sourceMap = sourceMap;
36 | }
37 | });
38 | });
39 | });
40 | }
41 |
42 | createSourceMapsPlugin.$inject = ['emitter', 'config.basePath', 'logger'];
43 |
44 | module.exports = {
45 | 'framework:sourcemaps': ['factory', createSourceMapsPlugin]
46 | };
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "atscript-playground",
3 | "private": true,
4 | "version": "0.0.0",
5 | "description": "A repo to play with AtScript.",
6 | "homepage": "https://github.com/vojtajina/atscript-playground",
7 | "repository": {
8 | "type": "git",
9 | "url": "git://github.com/vojtajina/atscript-playground.git"
10 | },
11 | "bugs": {
12 | "url": "https://github.com/vojtajina/atscript-playground/issues"
13 | },
14 | "dependencies": {
15 | "traceur": "^0.0.72",
16 | "requirejs": "^2.1.15"
17 | },
18 | "devDependencies": {
19 | "assert": "angular/assert#dist",
20 | "gulp": "^3.8.9",
21 | "gulp-connect": "^2.0.6",
22 | "gulp-rename": "^1.2.0",
23 | "gulp-traceur": "vojtajina/gulp-traceur#fix-sourcemaps",
24 | "karma": "^0.12.24",
25 | "karma-chrome-launcher": "^0.1.5",
26 | "karma-jasmine": "^0.2.2",
27 | "karma-requirejs": "^0.2.2",
28 | "karma-traceur-preprocessor": "^0.4.0"
29 | },
30 | "scripts": {
31 | "test": "karma start --single-run"
32 | },
33 | "author": "Vojta Jína ",
34 | "license": "Apache-2.0"
35 | }
36 |
--------------------------------------------------------------------------------
/src/abstract_factory/README.md:
--------------------------------------------------------------------------------
1 | ## Abstract Factory Pattern ##
2 |
3 | Creates an instance of several families of classes..
--------------------------------------------------------------------------------
/src/abstract_factory/abstractFactory.ats:
--------------------------------------------------------------------------------
1 | import {Logger} from '../logger';
2 |
3 | export class PetShop {
4 | constructor(petFactory:AbstractFactory) {
5 | this.petFactory = petFactory;
6 | this.logger = new Logger();
7 | }
8 |
9 | showPet() {
10 | var pet = this.petFactory.getPet();
11 | this.logger.log("We have a lovely " + pet.toString());
12 | this.logger.log("It says " + pet.speak());
13 | this.logger.log("We also have " + this.petFactory.getFood());
14 | }
15 | }
16 | /* Stuff that our factory makes */
17 |
18 | export class Animal {
19 | speak():string {
20 | throw new Error("Abstract method!");
21 | }
22 |
23 | toString():string {
24 | throw new Error("Abstract method!");
25 | }
26 | }
27 |
28 | export class Dog extends Animal {
29 | speak():string {
30 | return "woof";
31 | }
32 |
33 | toString():string {
34 | return "Dog";
35 | }
36 | }
37 |
38 | export class Cat extends Animal {
39 | speak():string {
40 | return "meow";
41 | }
42 |
43 | toString():string {
44 | return "Cat";
45 | }
46 | }
47 |
48 | /* Factory classes */
49 |
50 | export class AbstractFactory {
51 | getPet():Animal {
52 | throw new Error("Abstract method!");
53 | }
54 |
55 | getFood():string {
56 | throw new Error("Abstract method!");
57 | }
58 | }
59 |
60 | export class DogFactory extends AbstractFactory {
61 | getPet():Animal {
62 | return new Dog();
63 | }
64 |
65 | getFood():string {
66 | return "dog food"
67 | }
68 | }
69 |
70 | export class CatFactory extends AbstractFactory {
71 | getPet():Animal {
72 | return new Cat();
73 | }
74 |
75 | getFood():string {
76 | return "cat food"
77 | }
78 | }
--------------------------------------------------------------------------------
/src/abstract_factory/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Abstract Factory
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Abstract Factory
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/abstract_factory/runner.ats:
--------------------------------------------------------------------------------
1 | import {PetShop, CatFactory, DogFactory} from './abstractFactory';
2 |
3 | var petShop = new PetShop(new DogFactory());
4 | petShop.showPet();
--------------------------------------------------------------------------------
/src/adapter/README.md:
--------------------------------------------------------------------------------
1 | ## Adapter Pattern ##
2 |
3 | Convert the interface of class into another interface clients expect.Adapter lets class work together that couldn't otherwise because of incompatible interfaces.
4 |
5 | By GOF
--------------------------------------------------------------------------------
/src/adapter/adapter.ats:
--------------------------------------------------------------------------------
1 | /* Generic adapter class */
2 |
3 | export class Dog {
4 | constructor() {
5 | this.name = "Dog";
6 | }
7 |
8 | bark(): string {
9 | return "woof!";
10 | }
11 | }
12 |
13 | export class Cat {
14 | constructor() {
15 | this.name = "Cat"
16 | }
17 |
18 | meow(): string {
19 | return "meow!";
20 | }
21 | }
22 |
23 | export class Human {
24 | constructor() {
25 | this.name = "Human";
26 | }
27 |
28 | speak(): string {
29 | return "'hello'";
30 | }
31 | }
32 |
33 | export class Car {
34 | constructor() {
35 | this.name = "Car";
36 | }
37 |
38 | makeNoise(octaneLevel): string {
39 | return "vroom " + octaneLevel;
40 | }
41 | }
42 |
43 | export class Adapter{
44 | constructor(obj:any, adaptedMethod:string, ...args){
45 | this.name = obj.name;
46 | this.args = args;
47 | this.adaptedMethod = obj[adaptedMethod];
48 | }
49 |
50 | makeNoise(){
51 | return this.adaptedMethod(this.args);
52 | }
53 | }
--------------------------------------------------------------------------------
/src/adapter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Adapter
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Adapter
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/adapter/runner.ats:
--------------------------------------------------------------------------------
1 | import {Dog, Cat, Human, Car, Adapter} from './adapter';
2 | import { Logger } from '../logger';
3 |
4 | var logger = new Logger();
5 | var objects = [];
6 | var dog = new Dog();
7 |
8 | objects.push(new Adapter(dog, 'bark'));
9 |
10 | var cat = new Cat();
11 | objects.push(new Adapter(cat, 'meow'));
12 |
13 | var human = new Human();
14 | objects.push(new Adapter(human, 'speak'));
15 |
16 | var car = new Car();
17 | objects.push(new Adapter(car, 'makeNoise', 3));
18 |
19 | objects.forEach(adapter => {
20 | logger.log("A " + adapter.name + " goes " + adapter.makeNoise());
21 | });
--------------------------------------------------------------------------------
/src/bridge/README.md:
--------------------------------------------------------------------------------
1 | ## Bridge Pattern ##
2 |
3 | Decouple an abstraction from its implementation so that the two can vary independently.
4 |
5 | *By GOF*
--------------------------------------------------------------------------------
/src/bridge/bridge.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 | import { int, float } from '../lang';
3 |
4 | //Refined Abstraction
5 | export class CircleShape {
6 | constructor(x:int, y:int, radius:float, drawingApi:DrawingAPI) {
7 | this.x = x;
8 | this.y = y;
9 | this.radius = radius;
10 | this.drawingApi = drawingApi;
11 | }
12 |
13 | //low-level i.e. Implementation specific
14 | draw() {
15 | this.drawingApi.drawCircle(this.x, this.y, this.radius);
16 | }
17 |
18 | //high-level i.e. Abstraction specific
19 | scale(pct:float) {
20 | this.radius *= pct;
21 | }
22 | }
23 |
24 | export class DrawingAPI {
25 | constructor() {
26 | this.logger = new Logger();
27 | }
28 |
29 | drawCircle(x:int, y:int, radius:float) {
30 | throw new Error("Abstract method!");
31 | }
32 | }
33 |
34 | //ConcreteImplementor 1/2
35 | export class DrawingAPI1 extends DrawingAPI {
36 | drawCircle(x:int, y:int, radius:float) {
37 | this.logger.log('API1.circle at ' + x + ':' + y + ' radius ' + radius);
38 | }
39 | }
40 |
41 | // ConcreteImplementor 2/2
42 | export class DrawingAPI2 extends DrawingAPI {
43 | drawCircle(x:int, y:int, radius:float) {
44 | this.logger.log('API2.circle at ' + x + ':' + y + ' radius ' + radius);
45 | }
46 | }
--------------------------------------------------------------------------------
/src/bridge/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Bridge
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Bridge
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/bridge/runner.ats:
--------------------------------------------------------------------------------
1 | import {CircleShape, DrawingAPI1, DrawingAPI2} from './bridge';
2 |
3 | var shapes = [
4 | new CircleShape(1, 2, 3, new DrawingAPI1()),
5 | new CircleShape(5, 7, 11, new DrawingAPI2())
6 | ];
7 |
8 | shapes.forEach(shape=> {
9 | shape.scale(2.5);
10 | shape.draw();
11 | });
--------------------------------------------------------------------------------
/src/builder/README.md:
--------------------------------------------------------------------------------
1 | ##Builder Pattern##
2 |
3 | Solves the problem of telescoping constructor.
--------------------------------------------------------------------------------
/src/builder/builder.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | //Director
4 | export class Director {
5 | constructor() {
6 | this.builder = null;
7 | }
8 |
9 | construct(builder:Builder) {
10 | this.builder = builder;
11 | }
12 |
13 | constructBuilding() {
14 | this.builder.newBuilding();
15 | this.builder.buildFloor();
16 | this.builder.buildSize();
17 | }
18 |
19 | getBuilding() {
20 | return this.builder.building;
21 | }
22 | }
23 |
24 | //Abstract Builder
25 | export class Builder {
26 | constructor() {
27 | this.building = null;
28 | }
29 |
30 | buildFloor() {
31 | throw new Error("Abstract method!");
32 | }
33 |
34 | buildSize() {
35 | throw new Error("Abstract method!");
36 | }
37 |
38 | newBuilding() {
39 | this.building = new Building();
40 | }
41 | }
42 |
43 | // Concrete Builder
44 | export class HouseBuilder extends Builder {
45 | buildFloor() {
46 | this.building.floor = 'One';
47 | }
48 |
49 | buildSize() {
50 | this.building.size = 'Big';
51 | }
52 | }
53 |
54 | export class FlatBuilder extends Builder {
55 | buildFloor() {
56 | this.building.floor = 'More than One';
57 | }
58 |
59 | buildSize() {
60 | this.building.size = 'Small';
61 | }
62 | }
63 |
64 | //Product
65 | export class Building {
66 | constructor() {
67 | this.floor = null;
68 | this.size = null;
69 | }
70 |
71 | toString():string {
72 | return 'Floor: ' + this.floor + ' | Size: ' + this.size;
73 | }
74 | }
--------------------------------------------------------------------------------
/src/builder/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Builder
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Builder
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/builder/runner.ats:
--------------------------------------------------------------------------------
1 | import {Director, Builder, HouseBuilder, FlatBuilder, Building} from './builder'
2 | import { Logger } from '../logger';
3 |
4 | var logger = new Logger();
5 |
6 | var director = new Director();
7 |
8 | director.construct(new HouseBuilder());
9 | director.constructBuilding();
10 | var building1 = director.getBuilding()
11 | logger.log(building1.toString());
12 |
13 |
14 | director.construct(new FlatBuilder());
15 | director.constructBuilding();
16 | var building2 = director.getBuilding()
17 | logger.log(building2.toString());
--------------------------------------------------------------------------------
/src/command/README.md:
--------------------------------------------------------------------------------
1 | ##Command Pattern##
2 |
3 | Creates objects which encapsulate actions and parameters.
--------------------------------------------------------------------------------
/src/command/command.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | export class Command {
4 | constructor(receiver:Receiver) {
5 | this.logger = new Logger();
6 | this.receiver = receiver;
7 | }
8 |
9 | execute() {
10 | throw new Error("Abstract method!");
11 | }
12 | }
13 |
14 | export class ConcreteCommand1 extends Command {
15 | constructor(receiver:Receiver) {
16 | super(receiver);
17 | }
18 |
19 | execute() {
20 | this.logger.log("`execute` method of ConcreteCommand1 is being called!");
21 | this.receiver.action();
22 | }
23 | }
24 |
25 | export class ConcreteCommand2 extends Command {
26 | constructor(receiver:Receiver) {
27 | super(receiver);
28 | }
29 |
30 | execute() {
31 | this.logger.log("`execute` method of ConcreteCommand2 is being called!");
32 | this.receiver.action();
33 | }
34 | }
35 |
36 | export class Invoker {
37 | constructor() {
38 | this.commands = [];
39 | }
40 |
41 | storeAndExecute(cmd:Command) {
42 | this.commands.push(cmd);
43 | cmd.execute();
44 | }
45 | }
46 |
47 | export class Receiver {
48 | constructor() {
49 | this.logger = new Logger();
50 | }
51 |
52 | action() {
53 | this.logger.log("action is being called!");
54 | }
55 | }
--------------------------------------------------------------------------------
/src/command/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Command
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Command
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/command/runner.ats:
--------------------------------------------------------------------------------
1 | import {Receiver ,ConcreteCommand1 ,ConcreteCommand2 ,Invoker} from './command';
2 |
3 | var receiver = new Receiver();
4 | var command1 = new ConcreteCommand1(receiver);
5 | var command2 = new ConcreteCommand2(receiver);
6 | var invoker = new Invoker();
7 |
8 | invoker.storeAndExecute(command1);
9 | invoker.storeAndExecute(command2);
--------------------------------------------------------------------------------
/src/composite/README.md:
--------------------------------------------------------------------------------
1 | ##Composite Pattern##
2 |
3 | Composite pattern is used where we need to treat a group of objects in similar way as a single object.
--------------------------------------------------------------------------------
/src/composite/composite.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 | import { int, float } from '../lang';
3 |
4 |
5 | export class Employee {
6 | constructor(name:string, dept:string, sal:int) {
7 | this.subordinates = [];
8 | this.name = name;
9 | this.dept = dept;
10 | this.sal = sal;
11 | }
12 | add(e:Employee) {
13 | this.subordinates.push(e);
14 | }
15 | remove(e:Employee) {
16 |
17 | var index = this.subordinates.indexOf(e);
18 | if (index > -1) {
19 | this.subordinates.splice(index, 1);
20 | }
21 | }
22 |
23 | get Subordinates() {
24 | return this.subordinates;
25 | }
26 |
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/composite/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Composite
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Composite
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/composite/runner.ats:
--------------------------------------------------------------------------------
1 | import {Employee} from './composite';
2 | import { Logger } from '../logger';
3 |
4 | var logger = new Logger();
5 | var ceo = new Employee("John", "CEO", 30000);
6 | var headSales = new Employee("Robert", "Head Sales", 20000);
7 |
8 | var headMarketing = new Employee("Michel", "Head Marketing", 20000);
9 |
10 | var clerk1 = new Employee("Laura", "Marketing", 10000);
11 | var clerk2 = new Employee("Bob", "Marketing", 10000);
12 |
13 | var salesExecutive1 = new Employee("Richard", "Sales", 10000);
14 | var salesExecutive2 = new Employee("Rob", "Sales", 10000);
15 |
16 |
17 | ceo.add(headSales);
18 | ceo.add(headMarketing);
19 | headSales.add(salesExecutive1);
20 | headSales.add(salesExecutive2);
21 |
22 | headMarketing.add(clerk1);
23 | headMarketing.add(clerk2);
24 |
25 |
26 | logger.log(JSON.stringify(ceo));
27 | logger.log(JSON.stringify(headSales));
28 |
29 | //Refactor code. For loop
30 |
31 | ceo.subordinates.forEach(_ceo=> {
32 | logger.log(JSON.stringify(_ceo));
33 | });
34 |
35 |
--------------------------------------------------------------------------------
/src/decorator/README.md:
--------------------------------------------------------------------------------
1 | ##Decorator Pattern##
2 |
3 | Decorator pattern allows a user to add new functionality to an existing object without altering its structure.
4 | This type of design pattern comes under structural pattern as this pattern acts as a wrapper to existing class.
--------------------------------------------------------------------------------
/src/decorator/decorator.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | //Defined Interface
4 | export class Shape {
5 | constructor() {
6 | this.logger = new Logger();
7 | }
8 |
9 | draw() {
10 | throw new Error("Interface!");
11 | }
12 | }
13 | //Concrete Implementor 1/2
14 | export class Circle extends Shape {
15 |
16 | draw() {
17 | this.logger.log("Shape:Circle");
18 | }
19 | }
20 | //Concrete Implementor 2/2
21 | export class Rectangle extends Shape {
22 |
23 | draw() {
24 | this.logger.log("Shape:Rectangle");
25 | }
26 | }
27 | //Abstract class
28 | export class ShapeDecorator extends Shape {
29 | constructor(_decoratedShape:Shape) {
30 | this.decoratedShape = _decoratedShape;
31 | this.logger = new Logger();
32 | }
33 |
34 | draw() {
35 | this.decoratedShape.draw();
36 | }
37 | }
38 | //Concrete implementor of abstract class
39 | export class RedShapeDecorator extends ShapeDecorator {
40 | constructor(_decoratedShape:Shape) {
41 | this.redDecoratedShape = _decoratedShape;
42 | super(this.redDecoratedShape);
43 | }
44 |
45 | setRedBorder(redDecoratedShape:Shape) {
46 | this.logger.log("Border color: Red.");
47 | }
48 |
49 | draw() {
50 | this.redDecoratedShape.draw();
51 | this.setRedBorder(this.redDecoratedShape);
52 | }
53 | }
--------------------------------------------------------------------------------
/src/decorator/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Decorator
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Decorator
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/decorator/runner.ats:
--------------------------------------------------------------------------------
1 | import {Circle,Rectangle,RedShapeDecorator} from './decorator';
2 |
3 | var circle = new Circle();
4 | var redCircle = new RedShapeDecorator(new Circle());
5 | var redRectangle = new RedShapeDecorator(new Rectangle());
6 |
7 | circle.draw();
8 | redCircle.draw();
9 | redRectangle.draw();
10 |
--------------------------------------------------------------------------------
/src/facade/README.md:
--------------------------------------------------------------------------------
1 | ##Facade Pattern##
2 |
3 | A facade is an object that provides a simplified interface to a larger body of code.
--------------------------------------------------------------------------------
/src/facade/facade.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | export class AbstractFacade {
4 | constructor() {
5 | this.logger = new Logger();
6 | }
7 | }
8 | export class MonitorFacade extends AbstractFacade{
9 | setMonitor() {
10 | this.logger.log("You have Monitor.");
11 | }
12 | }
13 |
14 | export class KeyboardFacade extends AbstractFacade{
15 | setKeyboard() {
16 | this.logger.log("You have keyboard.");
17 | }
18 | }
19 |
20 | export class MouseFacade extends AbstractFacade{
21 | setMouse() {
22 | this.logger.log("You have mouse.");
23 | }
24 | }
25 | export class LaptopFacade extends AbstractFacade{
26 | setLaptop() {
27 | this.logger.log("You have laptop.");
28 | }
29 | }
30 | export class ComputerFacade extends AbstractFacade{
31 | constructor() {
32 | super();
33 | this.monitor = new MonitorFacade();
34 | this.keyboard = new KeyboardFacade();
35 | this.mouse = new MouseFacade();
36 | this.laptop = new LaptopFacade();
37 | }
38 | buildComputer() {
39 | this.monitor.setMonitor();
40 | this.keyboard.setKeyboard();
41 | this.mouse.setMouse();
42 | this.laptop.setLaptop();
43 | this.logger.log("You have built a computer.");
44 | }
45 | }
46 |
47 |
48 |
--------------------------------------------------------------------------------
/src/facade/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Facade
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Facade
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/facade/runner.ats:
--------------------------------------------------------------------------------
1 | import {ComputerFacade} from './facade';
2 |
3 | var computerFacade = new ComputerFacade();
4 | computerFacade.buildComputer();
--------------------------------------------------------------------------------
/src/factory_method/README.md:
--------------------------------------------------------------------------------
1 | ##Factory-Method Pattern##
2 |
3 | In Factory-Method pattern, object is created without exposing the creation logic to the client and refer to newly created object using a common interface.
--------------------------------------------------------------------------------
/src/factory_method/factorymethod.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | //Defined Interface
4 | export class Shape{
5 | constructor(){
6 | this.logger = new Logger();
7 | }
8 |
9 | draw(){
10 | throw new Error("Interface!");
11 | }
12 | }
13 | //Concrete implementor 1/3
14 | export class Square extends Shape {
15 | draw() {
16 | this.logger.log("Square is created!");
17 | }
18 | }
19 | //Concrete implementor 2/3}
20 | export class Rectangle extends Shape{
21 | draw(){
22 | this.logger.log("Rectangle is created!");
23 | }
24 | }
25 | //Concrete implementor 3/3
26 | export class Circle extends Shape{
27 | draw(){
28 | this.logger.log("Circle is created!")
29 | }
30 | }
31 | export class ShapeFactory{
32 | //use getShape method to get object of type shape
33 | getShape(shapeType:string):Shape{
34 | if(shapeType == null)
35 | return null;
36 | else if(shapeType === 'CIRCLE')
37 | return new Circle();
38 | else if(shapeType === 'RECTANGLE')
39 | return new Rectangle();
40 | else if(shapeType === 'SQUARE')
41 | return new Square();
42 | else
43 | return null;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/factory_method/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Factory-Method
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Factory-Method
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/factory_method/runner.ats:
--------------------------------------------------------------------------------
1 | import {ShapeFactory,Circle,Rectangle,Square} from './factorymethod';
2 |
3 | var shapeFactory = new ShapeFactory();
4 |
5 | //get an object of Circle and call its draw method.
6 | var circleShape = shapeFactory.getShape("CIRCLE");
7 |
8 | //call draw method of Circle
9 | circleShape.draw();
10 |
11 | //get an object of Rectangle and call its draw method.
12 | var rectangleShape = shapeFactory.getShape("RECTANGLE");
13 |
14 | //call draw method of Rectangle
15 | rectangleShape.draw();
16 |
17 | //get an object of Square and call its draw method.
18 | var squareShape = shapeFactory.getShape("SQUARE");
19 |
20 | //call draw method of circle
21 | squareShape.draw();
--------------------------------------------------------------------------------
/src/iterator/README.md:
--------------------------------------------------------------------------------
1 | ##Iterator Pattern##
2 |
3 | Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.
--------------------------------------------------------------------------------
/src/iterator/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Iterator
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Iterator
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/iterator/iterator.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | export class Aggregate {
4 | constructor() {
5 | this.items = [];
6 | }
7 |
8 | get Count() {
9 | return this.items.length;
10 | }
11 |
12 | }
13 | //Abstract class
14 | export class Iterator {
15 | firstObject():any {
16 | throw new Error("Abstract method!");
17 | }
18 |
19 | nextObject():any {
20 | throw new Error("Abstract method!");
21 | }
22 |
23 | currentObject():any {
24 | throw new Error("Abstract method!");
25 | }
26 |
27 | isDone():boolean {
28 | throw new Error("Abstract method!");
29 | }
30 | }
31 | //Concrete of Iterator
32 | export class ConcreteIterator extends Iterator {
33 |
34 | constructor(aggregate:Aggregate) {
35 | this._aggregate = aggregate;
36 | this._items = this._aggregate.items;
37 | this.index = 0;
38 | }
39 |
40 | firstObject():any {
41 | return this._items[0];
42 | }
43 |
44 | nextObject():any {
45 | var retVal = null;
46 | if (this.index < (this._aggregate.Count - 1))
47 | retVal = this._items[++this.index];
48 | else
49 | retVal = "There is no more item in the list!";
50 | return retVal;
51 | }
52 |
53 | isDone():boolean {
54 | return this.index >= (this._aggregate.Count - 1);
55 | }
56 |
57 | currentObject() {
58 | return this._items[this.index];
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/iterator/runner.ats:
--------------------------------------------------------------------------------
1 | import {ConcreteIterator,Aggregate} from './iterator';
2 | import { Logger } from '../logger';
3 | var logger = new Logger();
4 | var aggregate = new Aggregate();
5 | aggregate.items[0] = "ITEM 1";
6 | aggregate.items[1] = "ITEM 2";
7 | aggregate.items[2] = "ITEM 3";
8 | aggregate.items[3] = "ITEM 4";
9 |
10 | var iterator = new ConcreteIterator(aggregate);
11 |
12 | logger.log("Next object: " + iterator.nextObject());
13 | logger.log("Current object: " + iterator.currentObject());
14 | logger.log("Next object: " + iterator.nextObject());
15 | logger.log("First object: " + iterator.firstObject());
16 | logger.log("Next object: " + iterator.nextObject());
17 | if (iterator.isDone())
18 | logger.log("Iterator is done!");
19 | else {
20 | logger.log("Not yet!");
21 | }
22 | logger.log("Next object: " + iterator.nextObject());
23 |
--------------------------------------------------------------------------------
/src/lang.ats:
--------------------------------------------------------------------------------
1 | export function int() {
2 | };
3 | int.assert = function (value) {
4 | return value == null || typeof value == 'number' && value === Math.floor(value);
5 | };
6 |
7 | export function float() {
8 | };
9 | float.assert = function (value) {
10 | return value == null || typeof value == 'number';
11 | };
--------------------------------------------------------------------------------
/src/logger.ats:
--------------------------------------------------------------------------------
1 | export class Logger {
2 | constructor() {
3 | this.container = document.getElementById("logContainer");
4 | }
5 | log(message: string) {
6 | var li = document.createElement("li");
7 | li.appendChild(document.createTextNode(message));
8 | this.container.appendChild(li);
9 | }
10 | }
--------------------------------------------------------------------------------
/src/main.ats:
--------------------------------------------------------------------------------
1 | export class Main {
2 |
3 | }
--------------------------------------------------------------------------------
/src/memento/README.md:
--------------------------------------------------------------------------------
1 | ##Memento Pattern##
2 |
3 | Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.
--------------------------------------------------------------------------------
/src/memento/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Memento
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Memento
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/memento/memento.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 | import { int, float } from '../lang';
3 |
4 | export class Originator {
5 | constructor() {
6 | this.logger = new Logger();
7 | }
8 |
9 | set State(_state:string) {
10 | this.state = _state;
11 | }
12 |
13 | get State():string {
14 | return this.state;
15 | }
16 |
17 | set stateFromMemento(memento:Memento) {
18 | this.state = memento.MementoState;
19 | }
20 |
21 | get stateToBeSavedMemento():Memento {
22 | return (new Memento(this.state));
23 | }
24 |
25 | }
26 | export class Memento {
27 | constructor(_state:string) {
28 | this.mementoState = _state;
29 | }
30 |
31 | get MementoState():string {
32 | return this.mementoState;
33 | }
34 |
35 | }
36 | export class CareTaker {
37 | constructor() {
38 | this.mementoList = [];
39 | }
40 |
41 | addStateToMementoList(_state:Memento) {
42 | this.mementoList.push(_state);
43 | }
44 |
45 | getStateFromMementoList(index:int):Memento {
46 | return this.mementoList[index];
47 | }
48 | }
--------------------------------------------------------------------------------
/src/memento/runner.ats:
--------------------------------------------------------------------------------
1 | import {Originator,CareTaker} from './memento';
2 | import { Logger } from '../logger';
3 |
4 | var originator = new Originator();
5 | var careTaker = new CareTaker();
6 | var logger = new Logger();
7 | originator.State = "State #1";
8 | originator.State = "State #2";
9 | careTaker.addStateToMementoList(originator.stateToBeSavedMemento);
10 |
11 | originator.State = "State #3";
12 | careTaker.addStateToMementoList(originator.stateToBeSavedMemento);
13 | originator.State = "State #4";
14 | logger.log("Current state is: " + originator.State);
15 | originator.stateFromMemento = careTaker.getStateFromMementoList(0);
16 | logger.log("First saved state is: " + originator.State);
17 | originator.stateFromMemento = careTaker.getStateFromMementoList(1);
18 | logger.log("Second saved state is: " + originator.State);
19 |
20 |
--------------------------------------------------------------------------------
/src/mvc/README.md:
--------------------------------------------------------------------------------
1 | ##MVC Pattern##
2 |
3 | It divides a given software application into three interconnected parts, so as to separate internal representations of information from the ways that information is presented to or accepted from the user.
--------------------------------------------------------------------------------
/src/mvc/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | MVC
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | MVC
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/mvc/mvc.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | export class Student {
4 | get Number():string {
5 | return this.rollNo;
6 | }
7 |
8 | get Name():string {
9 | return this.studentName;
10 | }
11 |
12 | set Name(name:string) {
13 | this.studentName = name;
14 | }
15 |
16 | set Number(number:string) {
17 | this.rollNo = number;
18 | }
19 | }
20 | export class StudentView {
21 | constructor() {
22 | this.logger = new Logger();
23 | }
24 |
25 | printStudentDetails(name:string, number:string) {
26 | this.logger.log("Student:");
27 | this.logger.log("Name:" + name);
28 | this.logger.log("Roll no:" + number);
29 | }
30 | }
31 | export class StudentController {
32 | constructor(model:Student, view:StudentView) {
33 | this.studentModel = model;
34 | this.studentView = view;
35 | }
36 |
37 | get StudentName():string {
38 | return this.studentModel.Name;
39 | }
40 |
41 | get StudentNumber():string {
42 | return this.studentModel.Number;
43 | }
44 |
45 | set StudentName(name:string) {
46 | this.studentModel.Name = name;
47 | }
48 |
49 | set StudentNumber(number:string) {
50 | this.studentModel.Number = number;
51 | }
52 |
53 | updateView() {
54 | this.studentView.printStudentDetails(this.studentModel.Name, this.studentModel.Number);
55 | }
56 |
57 | }
58 | export class DBManager{
59 | retriveStudentFromDatabase():Student{
60 | var student = new Student();
61 | student.Name = "Robert";
62 | student.Number = "10";
63 | return student;
64 | }
65 | }
--------------------------------------------------------------------------------
/src/mvc/runner.ats:
--------------------------------------------------------------------------------
1 | import {Student,StudentController,StudentView,DBManager} from './mvc'
2 |
3 | //fetch student record based on his roll no from the database
4 | var db = new DBManager();
5 | var model = db.retriveStudentFromDatabase();
6 |
7 | //Create a view : to write student details on console
8 | var view = new StudentView();
9 |
10 | var controller = new StudentController(model, view);
11 | controller.updateView();
12 |
13 | //update model data
14 | controller.StudentName = "John";
15 | controller.StudentNumber = "15";
16 |
17 | controller.updateView();
--------------------------------------------------------------------------------
/src/observer/README.md:
--------------------------------------------------------------------------------
1 | ##Observer Pattern##
2 |
3 | Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.
--------------------------------------------------------------------------------
/src/observer/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Observer
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Observer
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/observer/observer.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 | import { int } from '../lang';
3 |
4 | export class Subject {
5 | constructor() {
6 | this.observers = [];
7 | this.logger = new Logger();
8 | }
9 |
10 | register(observer:Observer) {
11 | this.logger.log(observer.toString() + " is pushed!");
12 | this.observers.push(observer);
13 | }
14 |
15 | unregister(observer:Observer) {
16 | var n:int = this.observers.indexOf(observer);
17 | this.logger.log(observer.toString() + " is removed");
18 | this.observers.splice(n, 1);
19 | }
20 |
21 | notify() {
22 | this.logger.log("notify all the observers");
23 |
24 | for (var i = 0, max = this.observers.length; i < max; i += 1) {
25 | this.observers[i].notify();
26 | }
27 | }
28 | }
29 |
30 | export class ConcreteSubject extends Subject {
31 | get SubjectState():int {
32 | return this.subjectState;
33 | }
34 |
35 | set SubjectState(subjectState:int) {
36 | this.subjectState = subjectState;
37 | }
38 | }
39 |
40 |
41 | export class Observer {
42 | constructor() {
43 | this.logger = new Logger();
44 | }
45 |
46 | notify() {
47 | throw new Error("Abstract Method!");
48 | }
49 |
50 | toString():string {
51 |
52 | }
53 | }
54 |
55 | export class ConcreteObserver extends Observer {
56 | constructor(subject:ConcreteSubject, name:string) {
57 | super();
58 | this.logger.log("ConcreteObserver " + name + " is created!");
59 | this.subject = subject;
60 | this.name = name;
61 | }
62 |
63 | notify() {
64 | this.logger.log("ConcreteObserver's notify method");
65 | this.logger.log(this.name, this.state);
66 | this.state = this.subject.SubjectState;
67 | }
68 |
69 | get Subject():ConcreteSubject {
70 | return this.subject;
71 | }
72 |
73 | set Subject(subject:ConcreteSubject) {
74 | this.subject = subject;
75 | }
76 |
77 | toString():string {
78 | return this.name;
79 | }
80 | }
--------------------------------------------------------------------------------
/src/observer/runner.ats:
--------------------------------------------------------------------------------
1 | import {ConcreteSubject ,ConcreteObserver} from './observer';
2 |
3 |
4 | var sub = new ConcreteSubject();
5 |
6 | sub.register(new ConcreteObserver(sub, "Aaron"));
7 | sub.register(new ConcreteObserver(sub, "Swartz"));
8 | sub.register(new ConcreteObserver(sub, "Reddit"));
9 |
10 | sub.SubjectState = 123;
11 | sub.notify();
--------------------------------------------------------------------------------
/src/prototype/README.md:
--------------------------------------------------------------------------------
1 | ##Prototype Pattern##
2 |
3 | In the prototype pattern, a new object is created by cloning an existing object.
--------------------------------------------------------------------------------
/src/prototype/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Prototype
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Prototype
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/prototype/prototype.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 | import { int, float } from '../lang';
3 |
4 | export class Prototype {
5 |
6 | constructor(){
7 |
8 | }
9 |
10 | doClone():Prototype {
11 |
12 | throw new Error("Abstract method!");
13 | }
14 |
15 | }
16 |
17 | export class Person extends Prototype {
18 |
19 | constructor(surname:string) {
20 | this.logger = new Logger();
21 |
22 | this.surname = surname;
23 | }
24 |
25 | doClone():Prototype {
26 |
27 | return new Person(this.surname);
28 | }
29 |
30 | toString():string{
31 |
32 | return this.logger.log("This person is named " + this.surname);
33 | }
34 | }
35 |
36 |
37 | export class Dog extends Prototype {
38 |
39 | constructor(sound:string) {
40 | this.logger = new Logger();
41 |
42 | this.sound = sound;
43 | }
44 |
45 | doClone():Prototype {
46 |
47 | return new Dog(this.sound);
48 | }
49 |
50 | toString():string {
51 |
52 | return this.logger.log("This dog says " + this.sound);
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/src/prototype/runner.ats:
--------------------------------------------------------------------------------
1 | import {Prototype, Person, Dog} from './prototype';
2 |
3 |
4 | var person1 = new Person("Fred");
5 |
6 | var person2 = person1.doClone();
7 | person1.toString();
8 | person2.toString();
9 |
10 |
11 | var dog1 = new Dog("Wooof!");
12 | dog1.toString();
13 |
14 | var dog2 = dog1.doClone();
15 | dog2.toString();
--------------------------------------------------------------------------------
/src/proxy/README.md:
--------------------------------------------------------------------------------
1 | ##Proxy Pattern##
2 |
3 | Provide a surrogate or placeholder for another object to control access to it.
--------------------------------------------------------------------------------
/src/proxy/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Proxy
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Proxy
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/proxy/proxy.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | //Real Class
4 | export class Driving {
5 | constructor() {
6 | this.logger = new Logger();
7 | }
8 |
9 | startEngine() {
10 | this.logger.log("Engine is started.");
11 | }
12 |
13 | hitGas() {
14 | this.logger.log("Car is accelerated.");
15 | }
16 |
17 | hitBrake() {
18 | this.logger.log("Car is stopped.");
19 | }
20 |
21 | parkCark() {
22 | this.logger.log("Car is parked.");
23 | }
24 |
25 | stopEngine() {
26 | this.logger.log("Engine is stopped.");
27 | }
28 | }
29 | //Proxy Class
30 | export class ProxyDriving extends Driving {
31 | constructor() {
32 | this._driving = new Driving();
33 | }
34 |
35 | startEngine() {
36 | this._driving.startEngine();
37 | }
38 |
39 | hitGas() {
40 | this._driving.hitGas();
41 | }
42 |
43 | hitBrake() {
44 | this._driving.hitBrake();
45 | }
46 |
47 | parkCark() {
48 | this._driving.parkCark();
49 | }
50 |
51 | stopEngine() {
52 | this._driving.stopEngine();
53 | }
54 | }
--------------------------------------------------------------------------------
/src/proxy/runner.ats:
--------------------------------------------------------------------------------
1 | import {ProxyDriving} from './proxy';
2 |
3 | var proxy = new ProxyDriving();
4 | proxy.startEngine();
5 | proxy.hitGas();
6 | proxy.hitBrake();
7 | proxy.parkCark();
8 | proxy.stopEngine();
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/publish_subscribe/README.md:
--------------------------------------------------------------------------------
1 | ##Publish Subscribe##
--------------------------------------------------------------------------------
/src/publish_subscribe/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Publish Subscribe
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Publish Subscribe
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/publish_subscribe/pubsub.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | export class Provider {
4 | constructor() {
5 | this.msgQueue = []
6 | this.subscribers = {}
7 | }
8 |
9 | notify(msg:string) {
10 | this.msgQueue.push(msg)
11 | }
12 |
13 | subscribe(msg:string, subscriber:Subscriber) {
14 | if (!(msg in this.subscribers)) {
15 | this.subscribers[msg] = [];
16 | }
17 |
18 | this.subscribers[msg].push(subscriber);
19 | }
20 |
21 | unsubscribe(msg:string, subscriber:Subscriber) {
22 | var subscribers = this.subscribers[msg];
23 | var index = subscribers.indexOf(subscriber);
24 | if (index > -1) {
25 | subscribers.splice(index, 1);
26 | }
27 | }
28 |
29 | update() {
30 | var _that = this;
31 | this.msgQueue.forEach(msg=> {
32 | if (msg in this.subscribers) {
33 | _that.subscribers[msg].forEach(sub=> {
34 | sub.run(msg)
35 | });
36 | }
37 | });
38 |
39 | this.msgQueue = []
40 | }
41 | }
42 |
43 | export class Publisher {
44 | constructor(msgCenter:Provider) {
45 | this.provider = msgCenter;
46 | }
47 |
48 | publish(msg:string) {
49 | this.provider.notify(msg)
50 | }
51 | }
52 |
53 | export class Subscriber {
54 | constructor(name:string, msgCenter:Provider) {
55 | this.name = name;
56 | this.provider = msgCenter;
57 | this.logger = new Logger();
58 | }
59 |
60 | subscribe(msg:string) {
61 | this.provider.subscribe(msg, this);
62 | }
63 |
64 | run(msg:string) {
65 | this.logger.log(this.name + " & " + msg);
66 | }
67 | }
--------------------------------------------------------------------------------
/src/publish_subscribe/runner.ats:
--------------------------------------------------------------------------------
1 | import {Provider ,Subscriber,Publisher} from './pubsub';
2 |
3 |
4 | var messageCenter = new Provider();
5 |
6 | var fftv = new Publisher(messageCenter);
7 |
8 | var aaron = new Subscriber("aaron", messageCenter);
9 | aaron.subscribe("reddit");
10 |
11 | var aamir = new Subscriber("aamir", messageCenter);
12 | aamir.subscribe("movie");
13 |
14 | var gee = new Subscriber("turing", messageCenter);
15 | gee.subscribe("science");
16 |
17 | fftv.publish("reddit");
18 | fftv.publish("science");
19 | fftv.publish("ads");
20 | fftv.publish("movie");
21 | fftv.publish("reddit");
22 | fftv.publish("reddit");
23 | fftv.publish("science");
24 | fftv.publish("blank");
25 |
26 | messageCenter.update();
--------------------------------------------------------------------------------
/src/strategy/README.md:
--------------------------------------------------------------------------------
1 | ##Strategy Pattern##
2 |
3 | Creates objects which represent various strategies and a context object whose behavior varies as per its strategy object.
--------------------------------------------------------------------------------
/src/strategy/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Strategy
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Strategy
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/strategy/runner.ats:
--------------------------------------------------------------------------------
1 | import {Strategy, Context, OperationAdd,OperationSubstract,OperationMultiply} from './strategy';
2 |
3 |
4 |
5 | var contextAdd = new Context(new OperationAdd());
6 | var contextSub = new Context(new OperationSubstract());
7 | var contextMultiply = new Context(new OperationMultiply());
8 |
9 | contextAdd.executeStrategy(1,10);
10 | contextSub.executeStrategy(12,5);
11 | contextMultiply.executeStrategy(5,10);
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/strategy/strategy.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 | import { int, float } from '../lang';
3 |
4 |
5 | export class Strategy {
6 | constructor() {
7 | this.logger = new Logger();
8 |
9 | }
10 |
11 | doOperation(num1:int, num2:int) {
12 | throw new Error("Abstract method!");
13 | }
14 | }
15 | export class Context {
16 | constructor(strategy:Strategy) {
17 | this.strategy = strategy;
18 | }
19 |
20 | executeStrategy(num1:int, num2:int) {
21 | return this.strategy.doOperation(num1, num2);
22 | }
23 |
24 | }
25 | export class OperationAdd extends Strategy {
26 | doOperation(num1:int, num2:int) {
27 | this.logger.log("add of operation" + ':' + (num1 + num2).toString());
28 |
29 | }
30 | }
31 |
32 | export class OperationSubstract extends Strategy {
33 | doOperation(num1:int, num2:int) {
34 | this.logger.log('sub of operation' + ':' + (num1 - num2).toString());
35 | }
36 | }
37 |
38 | export class OperationMultiply extends Strategy {
39 | doOperation(num1:int, num2:int) {
40 | this.logger.log('multiply of operation' + ':' + (num1 * num2).toString());
41 | }
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/src/template/README.md:
--------------------------------------------------------------------------------
1 | ##Template Pattern##
2 |
3 | Template Method is a behavioral design pattern and it’s used to create a method stub and deferring some of the steps of implementation to the subclasses.
--------------------------------------------------------------------------------
/src/template/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Template
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Template
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/template/runner.ats:
--------------------------------------------------------------------------------
1 | import {HouseTemplate,WoodenHouse,GlassHouse} from './template';
2 |
3 | var glassHouse = new GlassHouse();
4 |
5 | glassHouse.buildHouse();
6 |
7 | var woodenHouse = new WoodenHouse();
8 | woodenHouse.buildHouse();
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/template/template.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 |
3 | export class HouseTemplate {
4 | constructor() {
5 | this.logger = new Logger();
6 | }
7 |
8 | //Template method, final so subclasses can't override
9 | buildHouse() {
10 | this.buildFoundation();
11 | this.buildPillars();
12 | this.buildWalls();
13 | this.buildWindows();
14 | this.logger.log("House is built.");
15 | this.logger.log("***************");
16 |
17 | }
18 |
19 | //Always same for all kinds of concrete classes so it is implemented in base.
20 | buildFoundation() {
21 | this.logger.log("Building foundation with cement,iron rods and sand");
22 | }
23 |
24 | //Always same for all kinds of concrete classes so it is implemented in base.
25 | buildWindows() {
26 | this.logger.log("Building glass windows");
27 | }
28 |
29 | //Abstract method which is to be implemented in concrete classes
30 | buildPillars() {
31 | throw new Error("Abstract Method!");
32 | }
33 |
34 | //Abstract method which is to be implemented in concrete classes
35 | buildWalls() {
36 | throw new Error("Abstract Method!");
37 | }
38 |
39 |
40 | }
41 | //Concrete implementor 1/2
42 | export class WoodenHouse extends HouseTemplate {
43 | buildWalls() {
44 | this.logger.log("Building wooden walls.");
45 | }
46 |
47 | buildPillars() {
48 | this.logger.log("Building pillars with wooden coating.");
49 | }
50 | }
51 | //Concrete implementor 2/2
52 | export class GlassHouse extends HouseTemplate {
53 | buildWalls() {
54 | this.logger.log("Building glass walls.");
55 | }
56 |
57 | buildPillars() {
58 | this.logger.log("Building pillars with glass coating.");
59 | }
60 | }
--------------------------------------------------------------------------------
/src/visitor/README.md:
--------------------------------------------------------------------------------
1 | ##Visitor Pattern##
2 |
3 | A visitor class which changes the executing algorithm of an element class.
4 |
--------------------------------------------------------------------------------
/src/visitor/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Visitor
4 |
5 |
6 |
7 | Home
8 |
9 |
10 | Visitor
11 |
14 |
15 |
16 |
17 |
18 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/visitor/runner.ats:
--------------------------------------------------------------------------------
1 | import {
2 | ComputerPart,
3 | Computer,
4 | ComputerPartVisitor,
5 | ComputerPartDisplayVisitor,
6 | Mouse,
7 | Keyboard,
8 | Monitor
9 | } from './visitor';
10 |
11 |
12 | var computerPart = new Computer();
13 | computerPart.accept(new ComputerPartDisplayVisitor());
14 |
--------------------------------------------------------------------------------
/src/visitor/visitor.ats:
--------------------------------------------------------------------------------
1 | import { Logger } from '../logger';
2 | import { int, float } from '../lang';
3 |
4 |
5 | export class ComputerPart {
6 | accept(computerPartVisitor:ComputerPartVisitor) {
7 | throw new Error("Abstract Method!");
8 | }
9 | }
10 |
11 | export class Keyboard extends ComputerPart {
12 | accept(computerPartVisitor:ComputerPartVisitor) {
13 | computerPartVisitor.visitKeyboard(this);
14 | }
15 | }
16 |
17 | export class Monitor extends ComputerPart {
18 | accept(computerPartVisitor:ComputerPartVisitor) {
19 | computerPartVisitor.visitMonitor(this);
20 | }
21 | }
22 |
23 | export class Mouse extends ComputerPart {
24 | accept(computerPartVisitor:ComputerPartVisitor) {
25 | computerPartVisitor.visitMouse(this);
26 | }
27 | }
28 |
29 |
30 | export class Computer extends ComputerPart {
31 | constructor() {
32 | this.parts = [new Mouse, new Keyboard(), new Monitor()];
33 | }
34 |
35 | accept(computerPartVisitor:ComputerPartVisitor) {
36 | this.parts.forEach(part=> {
37 | part.accept(computerPartVisitor);
38 | });
39 | computerPartVisitor.visitComputer(this);
40 | }
41 | }
42 |
43 | export class ComputerPartVisitor {
44 | constructor() {
45 | this.logger = new Logger();
46 | }
47 |
48 | visitComputer(computer:Computer) {
49 | throw new Error("Abstract Method!");
50 | }
51 |
52 | visitMouse(mouse:Mouse) {
53 | throw new Error("Abstract Method!");
54 | }
55 |
56 | visitKeyboard(keyboard:Keyboard) {
57 | throw new Error("Abstract Method!");
58 | }
59 |
60 | visitMonitor(monitor:Monitor) {
61 | throw new Error("Abstract Method!");
62 | }
63 | }
64 |
65 | export class ComputerPartDisplayVisitor extends ComputerPartVisitor {
66 | visitComputer(computer:Computer) {
67 | this.logger.log("Displaying Computer.");
68 | }
69 |
70 | visitMouse(mouse:Mouse) {
71 | this.logger.log("Displaying Mouse.");
72 | }
73 |
74 | visitKeyboard(keyboard:Keyboard) {
75 | this.logger.log("Displaying Keyboard.");
76 | }
77 |
78 | visitMonitor(monitor:Monitor) {
79 | this.logger.log("Displaying Monitor.");
80 | }
81 | }
--------------------------------------------------------------------------------
/wait_for_watcher.js:
--------------------------------------------------------------------------------
1 | // Wait for any outstanding Traceur watchers.
2 | // Hack to work-around https://youtrack.jetbrains.com/issue/WEB-14104
3 |
4 | // How it works?
5 | // WebStorm Traceur watcher writes LOCK_FILE when running and delete LOCK_FILE once all watchers are finished.
6 | // WebStorm Karma configuration waits for this process to finish (i.e. till the LOCK_FILE is removed).
7 |
8 | var fs = require('fs');
9 | var LOCK_FILE = '.atscriptwatcher';
10 | var START_DELAY = 500;
11 |
12 | setTimeout(function() {
13 | if (!fs.existsSync(LOCK_FILE)) {
14 | // Watcher was not running.
15 | process.exit(0);
16 | }
17 |
18 | fs.watch(LOCK_FILE, function() {
19 | if (!fs.existsSync(LOCK_FILE)) {
20 | // All watchers have finished.
21 | process.exit(0);
22 | }
23 | });
24 | }, START_DELAY);
25 |
26 |
27 |
--------------------------------------------------------------------------------
/webstorm_traceur.js:
--------------------------------------------------------------------------------
1 | var inputFilename = process.argv[2];
2 | var outputFilename = process.argv[3] || inputFilename.replace(/\.ats$/, '.js');
3 |
4 | var path = require('path');
5 | var sourceRoot = path.relative(path.dirname(outputFilename), '');
6 |
7 | var TraceurNodeCompiler = require('traceur/src/node/NodeCompiler').NodeCompiler;
8 | var options = require('./config.json').traceur;
9 | var compiler = new TraceurNodeCompiler(options);
10 |
11 |
12 | // Increment the lock to delay Karma unit tests until all watchers are finished.
13 | var LOCK_FILE = '.atscriptwatcher';
14 | var fs = require('fs');
15 |
16 | if (fs.existsSync(LOCK_FILE)) {
17 | var lockCount = parseInt(fs.readFileSync(LOCK_FILE).toString(), 10);
18 | lockCount++;
19 | fs.writeFileSync(LOCK_FILE, lockCount.toString());
20 | } else {
21 | fs.writeFileSync(LOCK_FILE, '1');
22 | }
23 |
24 |
25 | // TODO(vojta): Fix this in Traceur instead.
26 | // Traceur generates source map file in the CWD.
27 | // This hacks Traceur to generate source map file in the output file directory, respecting the `sourceRoot` option.
28 | var writeFile = require('traceur/src/node/file-util').writeFile;
29 | compiler.writeTreeToFile = function(tree, filename) {
30 | filename = this.normalize(filename);
31 | // This is changed.
32 | // Pass sourceRoot to `this.write`. Traceur does not pass it through.
33 | var compiledCode = this.write(tree, filename, sourceRoot);
34 | if (this.options_.sourceMaps === 'file') {
35 | var sourcemap = this.getSourceMap();
36 | if (sourcemap) {
37 | // This is changed.
38 | // Generate the source map in the same folder as the output JS file.
39 | writeFile(filename.replace(/\.js$/, '.map'), sourcemap);
40 | }
41 | }
42 |
43 | writeFile(filename, compiledCode);
44 | };
45 |
46 |
47 | compiler.compileSingleFile(inputFilename, outputFilename, function(err) {
48 | console.error(err);
49 | });
50 |
51 | // Release/decrement the lock.
52 | var lockCount = parseInt(fs.readFileSync(LOCK_FILE).toString(), 10);
53 | lockCount--;
54 |
55 | if (lockCount === 0) {
56 | fs.unlinkSync(LOCK_FILE);
57 | } else {
58 | fs.writeFileSync(LOCK_FILE, lockCount.toString());
59 | }
60 |
--------------------------------------------------------------------------------