Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorator #222

Open
Tracked by #116
simonsan opened this issue Feb 22, 2021 · 3 comments
Open
Tracked by #116

Decorator #222

simonsan opened this issue Feb 22, 2021 · 3 comments
Labels
A-pattern Area: Content about Patterns C-addition Category: Adding new content, something that didn't exist in the repository before C-needs discussion Area: Something that is not clear to everyone if it fixes something/adds valuable content
Projects

Comments

@simonsan
Copy link
Collaborator

Tracking issue for merging: https://github.com/lpxxn/rust-design-pattern/blob/master/structural/decorator.rs

Example:

use std::rc::Rc;

// The base Component trait defines operations that can be altered by
// decorators.
trait Component {
    fn operation(&self) -> String;
}

// Concrete Components provide default implementations of the operations.
// There might be several variations of these classes.
struct ConcreteComponent {}

impl Component for ConcreteComponent {
    fn operation(&self) -> String {
        "ConcreteComponent".to_string()
    }
}

// The base Decorator class follows the same interface as the other
// components. The primary purpose of this class is to define the wrapping
// interface for all concrete decorators. The default implementation of the
// wrapping code might include a field for storing a wrapped component and
// the means to initialize it.
trait Decorator: Component {
    fn new(component: Rc<dyn Component>) -> Self;
}

// Concrete Decorators call the wrapped object and alter its result in some
// way.
struct ConcreteDecoratorA {
    component: Rc<dyn Component>,
}

impl Decorator for ConcreteDecoratorA {
    fn new(component: Rc<dyn Component>) -> Self {
        ConcreteDecoratorA { component }
    }
}

impl Component for ConcreteDecoratorA {
    fn operation(&self) -> String {
        format!("ConcreteDecoratorA: {}", self.component.operation())
    }
}

struct ConcreteDecoratorB {
    component: Rc<dyn Component>,
}

impl Decorator for ConcreteDecoratorB {
    fn new(component: Rc<dyn Component>) -> Self {
        ConcreteDecoratorB { component }
    }
}

impl Component for ConcreteDecoratorB {
    fn operation(&self) -> String {
        format!("ConcreteDecoratorB: {}", self.component.operation())
    }
}

// The client code works with all objects using the Component interface.
// This way it can stay independent of the concrete classes of
// components it works with.
struct Client;

impl Client {
    fn client_code<T: Component>(component: &T) {
        println!("result: {}", component.operation())
    }
}

fn main() {
    let component = Rc::new(ConcreteComponent {});
    println!("client: i get a simple component: ");
    Client::client_code(component.as_ref());
    println!("client: now I've got a decorated component:");
    let decorator_a1 = ConcreteDecoratorA::new(component.clone());
    Client::client_code(&decorator_a1);

    let decorator_a2 = ConcreteDecoratorB::new(Rc::new(decorator_a1));
    Client::client_code(&decorator_a2);
}

@simonsan simonsan added C-addition Category: Adding new content, something that didn't exist in the repository before A-pattern Area: Content about Patterns labels Feb 22, 2021
@simonsan
Copy link
Collaborator Author

Tracking discussion on merging: lpxxn/rust-design-pattern#7

@simonsan simonsan added this to ToDo-Patterns in Content Feb 22, 2021
@simonsan
Copy link
Collaborator Author

simonsan commented Feb 22, 2021

@pickfire
Copy link
Contributor

URL broken.

Is the example even considered decorator? Shouldn't it be something like actix-web-codegen or rocket proc macro that looks more like a decorator?

@simonsan simonsan added the C-needs discussion Area: Something that is not clear to everyone if it fixes something/adds valuable content label Feb 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-pattern Area: Content about Patterns C-addition Category: Adding new content, something that didn't exist in the repository before C-needs discussion Area: Something that is not clear to everyone if it fixes something/adds valuable content
Projects
Content
ToDo-Patterns
Development

No branches or pull requests

2 participants