Está en la página 1de 9

TALLER 1 - PATRONES GOF - 2021-2

ESCUELA COLOMBIANA DE INGENIERÍA


CICLOS DE VIDA DE DESARROLLO DE SOFTWARE
PARTE I. - CLASIFICACIÓN
DIEGO LEÓN BALLÉN

Tome como base el siguiente link para solucionar el taller


https://refactoring.guru/design-patterns/catalog

1. Enumere y defina las tres categorías de los patrones GoF.

- Patrones Creacionales: Proporcionan mecanismos de creación de objetos, que


aumentan la flexibilidad y la reutilización del código existente.

- Patrones Estructurales: Explican cómo ensamblar objetos y clases en estructuras


más grandes manteniéndolas flexibles y eficientes.

- Patrones de Comportamiento: Se relacionan con algoritmos y la asignación de


responsabilidades entre objetos.

2. Para cada una de las categorías seleccione al menos 2 patrones y explique que
problema solucionan y de un ejemplo en código de cómo se debe implementar.

Patrones Creacionales:
a) Factory Method (Método de fábrica): Es un patrón de diseño de creación que
proporciona una interfaz para crear objetos en una superclase, pero a la vez
permite la alteración del tipo de objetos que se crearán por parte de las
subclases.
● Problema:
○ Cuando no se sabe de antemano los tipos exactos y las
dependencias de los objetos con los que debería funcionar el
código.
○ Cuando desee proporcionar a los usuarios de su biblioteca o
marco una forma de ampliar sus componentes internos.
○ Cuando desee ahorrar recursos del sistema reutilizando
objetos existentes en lugar de reconstruirlos cada vez.

- Solución: El método de fábrica sugiere que reemplace las llamadas de construcción


de objetos directos con llamadas a un método de fábrica especial. Los objetos
devueltos por un método de fábrica a menudo se denominan productos.

public class Dialog{


public abstract Button createButton();
public void render(){
Button okButton = createButton();
okButton.onClick(closeDialog);
okButton.render();
}
}
public class WindowsDialog extends Dialog{
public Button createButton(){
return new WindowsButton();
}
}
public class WebDialog extends Dialog{
public Button createButton(){
return new HTMLButton();
}
}
public interface Button{
public void render();
public void onClick(f);
}
public class WindowsButton implements Button{
public void render(a, b){
}
public void onClick(f){
}
}
public class HTMLButton implements Button{
public void render(a, b){
}
public void onClick(f){
}
}
public class Application{
public Dialog field dialog;
public void initialize(){
config = readApplicationConfigFile();
if (config.OS == "Windows") {
dialog = new WindowsDialog();
}
else if (config.OS == "Web") {
dialog = new WebDialog();
}
else{
throw new Exception("Error! Unknown operating system.")
}
}
public main(){
this.initialize()
dialog.render()
}
}
b) Singleton: Es un patrón de diseño de creación que le permite asegurarse de
que una clase tenga solo una instancia, al tiempo que proporciona un punto
de acceso global a esta instancia.
● Problema:
○ Cuando una clase en su programa deba tener una sola
instancia disponible para todos los clientes.
○ Cuando necesite un control más estricto sobre las variables
globales.

- Solución: Como no tiene constructor público entonces la única forma de obtener el


objeto es llamar al método estático getInstance como constructor.

public class Database{


private static Database field instance;
private constructor Database(){
}
public static Database getInstance(){
if (Database.instance == null) {
acquireThreadLock();
if (Database.instance == null) {
Database.instance = new Database();
}
}
return Database.instance
}
public static void query(sql){
}
}
public class Application{
public main(){
Database foo = Database.getInstance();
foo.query("SELECT ...");
Database bar = Database.getInstance();
bar.query("SELECT ...");
}
}

Patrones Estructurales:

a) Adaptador: Es un patrón de diseño estructural que permite la colaboración de


objetos con interfaces incompatibles.
● Problema:
○ Cuando se quiera usar alguna clase existente, pero su interfaz no es
compatible con el resto del código.
○ Cuando desee reutilizar varias subclases existentes que carecen de
alguna funcionalidad común que no se puede agregar a la superclase.
- Solución: Crear un adaptador, que convierte la interfaz de un objeto para que otro
pueda entenderlo.

public class RoundHole{


public float radius;
public RoundHole(radius){
this.radius = radius;
}
public float getRadius(){
return this.radius;
}
public boolean fits(peg: RoundPeg){
return this.getRadius() >= peg.getRadius()
}
}
public class RoundPeg{
public float radius;
public RoundPeg(radius) {
this.radius = radius;
}
public float getRadius(){
return this.radius;
}
}
class SquarePeg{
public float width;
public SquarePeg(width){
this.width = width;
}
public float getWidth(){
return this.width;
}
}
class SquarePegAdapter extends RoundPeg{
private SquarePeg field peg;
public SquarePegAdapter(SquarePeg peg){
this.peg = peg
}
public float getRadius(){
return peg.getWidth() * Math.sqrt(2) / 2
}
hole = new RoundHole(5);
rpeg = new RoundPeg(5);
hole.fits(rpeg);
small_sqpeg = new SquarePeg(5);
large_sqpeg = new SquarePeg(10);
hole.fits(small_sqpeg);
small_sqpeg_adapter = new SquarePegAdapter(small_sqpeg);
large_sqpeg_adapter = new SquarePegAdapter(large_sqpeg);
hole.fits(small_sqpeg_adapter);
hole.fits(large_sqpeg_adapter);
b) Puente(Bridge): Es un patrón de diseño estructural que le permite dividir una clase
grande o un conjunto de clases relacionadas en dos jerarquías separadas que se
pueden desarrollar independientemente una de la otra.
● Problema:
○ Cuando desee dividir y organizar una clase monolítica que tenga
varias variantes de alguna funcionalidad.
○ Cuando necesite ampliar una clase en varias dimensiones
ortogonales.
○ Cuando necesita poder cambiar implementaciones en tiempo de
ejecución.
- Solución: Pasar de la herencia a la composición del objeto.
public class RemoteControl{
protected Device field device;
public void RemoteControl(Device device){
this.device = device
}
public void togglePower(){
if (device.isEnabled()){
device.disable();
}
else{
device.enable();
}
}
public void volumeDown(){
device.setVolume(device.getVolume() - 10)
}
public void volumeUp(){
device.setVolume(device.getVolume() + 10)
}
public void channelDown(){
device.setChannel(device.getChannel() - 1)
}
public void channelUp(){
device.setChannel(device.getChannel() + 1)}
}
}
public class AdvancedRemoteControl extends RemoteControl{
public void mute(){
device.setVolume(0)
}
}
interface Device{
public void isEnabled();
public void enable();
public void disable();
public void getVolume();
public void setVolume(int percent);
public void getChannel();
public void setChannel(Channel channel);
}
public class Tv implements Device{}
public class Radio implements Device{}
tv = new Tv();
remote = new RemoteControl(tv);
remote.togglePower();
radio = new Radio();
remote = new AdvancedRemoteControl(radio);

Patrones de comportamiento:
a) Chain of Responsibility(Cadena de responsabilidad): Es un patrón de diseño de
comportamiento que le permite pasar solicitudes a lo largo de una cadena de
controladores. Al recibir una solicitud, cada controlador decide procesar la solicitud o
pasarla al siguiente controlador de la cadena.
● Problema:
○ Cuando se espera que su programa procese diferentes tipos de
solicitudes de varias maneras, pero los tipos exactos de solicitudes y
sus secuencias se desconocen de antemano.
○ Cuando sea esencial para ejecutar varios controladores en un orden
particular.
○ Cuando se supone que el conjunto de controladores y su orden deben
cambiar en tiempo de ejecución.
- Solución: Transforma comportamientos particulares en objetos independientes
llamados manejadores.

public interface ComponentWithContextualHelp{


public void showHelp();
}
abstract class Component implements ComponentWithContextualHelp{
public string field tooltipText;
protected Container field container;
public return showHelp(){
if (tooltipText != null){
}
else{
container.showHelp();
}
}
}
abstract class Container extends Component{
protected array of Component field children;
public void add(child){
children.add(child);
child.container = this;
}
}
public class Button extends Component {
}
public class Panel extends Container{
field string modalHelpText;
public void showHelp(){
if (modalHelpText != null){
}
else{
super.showHelp();
}
}
public class Dialog extends Container{
public field string wikiPageURL;
public void showHelp(){
if (wikiPageURL != null) {
}
else{
super.showHelp();
}
}
}
public class Application{
public void createUI(){
dialog = new Dialog("Budget Reports");
dialog.wikiPageURL = "http://...";
panel = new Panel(0, 0, 400, 800);
panel.modalHelpText = "This panel does..." ;
ok = new Button(250, 760, 50, 20, "OK");
ok.tooltipText = "This is an OK button that..." ;
cancel = new Button(320, 760, 50, 20, "Cancel") ;
panel.add(ok);
panel.add(cancel);
dialog.add(panel);
}
public void onF1KeyPress(){
component = this.getComponentAtMouseCoords();
component.showHelp();
}
}

b) Comando: Es un patrón de diseño de comportamiento que convierte una solicitud en


un objeto independiente que contiene toda la información sobre la solicitud. Esta
transformación le permite pasar solicitudes como argumentos de método, retrasar o
poner en cola la ejecución de una solicitud y admitir operaciones que se pueden
deshacer.
● Problema:
○ Cuando desee parametrizar objetos con operaciones.
○ Cuando desee poner en cola operaciones, programar su ejecución o
ejecutarlas de forma remota.
○ Cuando desee implementar operaciones reversibles.
- Solución:

abstract class Command{


protected Application field app;
protected Editor field editor;
protected text field backup;
void Command(app: Application, editor: Editor){
this.app = app;
this.editor = editor;
}

public void saveBackup(){


backup = editor.text;
}
public void undo(){
editor.text = backup;
}
abstract method execute();
}
public class CopyCommand extends Command {
public boolean execute() {
app.clipboard = editor.getSelection();
return false;
}
}
public class CutCommand extends Command {
public boolean execute() {
saveBackup();
app.clipboard = editor.getSelection();
editor.deleteSelection();
return true;
}
}
public class PasteCommand extends Command {
public boolean execute(){
saveBackup();
editor.replaceSelection(app.clipboard);
return true;
}
}
public class UndoCommand extends Command {
public boolean execute(){
app.undo();
return false;
}
}
public class CommandHistory {
private array of Command field history;
public void push(Command c){
}
public Command pop(){
}
}
public class Editor {
private field String text;
public void Editor(String text){
this.text = text;
}
public String getSelection(){
return this.text;
}
public void deleteSelection(){
this.text = “”;
}
public void replaceSelection(String text){
this.text = text;
}
}
public class Application{
field string clipboard;
field array of Editors editors;
field Editor activeEditor;
field CommandHistory history;
public void createUI(){
copy = executeCommand(new CopyCommand(this, activeEditor)) ;
copyButton.setCommand(copy);
shortcuts.onKeyPress("Ctrl+C", copy);
cut = executeCommand(new CutCommand(this, activeEditor));
cutButton.setCommand(cut);
shortcuts.onKeyPress("Ctrl+X", cut);
paste = executeCommand(new PasteCommand(this, activeEditor));
pasteButton.setCommand(paste);
shortcuts.onKeyPress("Ctrl+V", paste);
undo = executeCommand(new UndoCommand(this, activeEditor));
undoButton.setCommand(undo);
shortcuts.onKeyPress("Ctrl+Z", undo);
}
public executeCommand(Command command){
if (command.execute){
history.push(command)
}
}
public void undo() {
command = history.pop();
if (command != null){
command.undo()
}
}
}

También podría gustarte