写点什么

架构师训练营第 3 周作业

用户头像
Season
关注
发布于: 2020 年 06 月 24 日

1. 请在草稿纸上手写一个单例模式的实现代码,拍照提交作业。

单例模式是开发过程中比较常见的模式,主要的实现有:饿汉式、懒汉式和双重加载。一般来说用饿汉式即可,如果需要懒加载则采用懒汉式,考虑到懒汉式的性能问题,可以进一步用双重检查的实现方式。以下是三种方式的实现。

1.1 饿汉式
1.2 懒汉式


1.3 双重检查

注意:这里并不需要 volatile 修饰 Instance,加 volatile 是为了防止指令重排,导致程序获取到未初始化时的实例,在高版本的 JDK 并不存在。


2. 请用组合设计模式编写程序,打印输出图 1 的窗口,窗口组件的树结构如图 2 所示,打印输出示例参考图 3。



2.1 功能分析

设计的类图主要如下:

其中, Component 是组件类,也是组合模式的接口,Control 是组合模式的叶子,Container 是组合模式的节点。考虑到显示方式的可扩展,这里新增了一个 Painter 接口,StdPainter 实现该接口,主要功能是将组件按一定格式(format)输出到控制台。

1.4 总结

平时开发中用饿汉式或者框架(比如 spring)提供的单例即可,没有必要过度设计。

2.2 Java 版

这里采用两种语言来实现,首先是 Java 的

public interface Painter {    void paint(Component component);}
public class StdPainter implements Painter{ private String format;
public StdPainter(String format) { this.format = format; }
@Override public void paint(Component component) { System.out.println(String.format(format, component.getClass().getSimpleName(), component.getName())); }}
public interface Component { String getName(); void render(Painter painter);}
public abstract class AbstractComponent implements Component{
String name;
public AbstractComponent(String name) { this.name = name; }
@Override public String getName() { return name; }}
public class Control extends AbstractComponent {
public Control(String name) { super(name); }
@Override public void render(Painter painter) { painter.paint(this); }}
public class Container extends AbstractComponent {
List<Component> children = new ArrayList<>();
public Container(String name) { super(name); }
public Container addChild(Component component) { this.children.add(component); return this; }
@Override public void render(Painter painter) { painter.paint(this); children.forEach(c -> c.render(painter)); }}
public class WinForm extends Container { public WinForm(String name) { super(name); }}
public class Frame extends Container { public Frame(String name) { super(name); }}
public class Button extends Control { public Button(String name) { super(name); }}
public class Label extends Control { public Label(String name) { super(name); }}
public class TextBox extends Control { public TextBox(String name) { super(name); }}
public class PasswordBox extends Control { public PasswordBox(String name) { super(name); }}
public class Picture extends Control { public Picture(String name) { super(name); }}
public class LinkLabel extends Control { public LinkLabel(String name) { super(name); }}
/** * 运行的主程序 */public class Application { public static void main(String[] args) { final Container win = new WinForm("WINDOW窗口") .addChild(new Picture("LOGO图片")) .addChild(new Button("登录")) .addChild(new Button("注册")) .addChild(new Frame("FRAME1") .addChild(new Label("用户名")) .addChild(new TextBox("文本框")) .addChild(new Label("密码")) .addChild(new PasswordBox("密码框")) .addChild(new TextBox("记住用户名")) .addChild(new LinkLabel("忘记密码")) ); win.render(new StdPainter("print %s(%s)")); }}
复制代码


运行效果


2.3 Golang 版


package main
import ( "fmt" "strings")
type Component interface { GetName() string render(painter Painter)}
type Painter interface { paint(component Component)}
type StdPainter struct { format string;}
func (p *StdPainter) paint(component Component) { typeName := fmt.Sprintf("%T", component) simpleTypeName := typeName[strings.LastIndex(typeName, ".")+1:] fmt.Printf(p.format, simpleTypeName, component.GetName())}
type Control struct { name string}
func (c *Control) GetName() string { return c.name}
func (c *Control) render(painter Painter) { painter.paint(c)}
type Container struct { name string children []Component}
func (c *Container) GetName() string { return c.name}
func (c *Container) AddChild(component Component) *Container { c.children = append(c.children, component) return c}
func (c *Container) render(painter Painter) { painter.paint(c) for _, child := range c.children { child.render(painter) }}
type WinForm struct { Container}
type Frame struct { Container}
type Picture struct { Control}
type Button struct { Control}
type Label struct { Control}
type TextBox struct { Control}
type PasswordBox struct { Control}
type LinkLabel struct { Control}
func main() { frame := &Frame{Container{ name: "FRAME1", children: []Component{ &Label{Control{name: "用户名"}}, &TextBox{Control{name: "文本框"}}, &Label{Control{name: "密码"}}, &PasswordBox{Control{name: "密码框"}}, &TextBox{Control{name: "记住用户名"}}, &LinkLabel{Control{name: "忘记密码"}}, }, }}
win := &WinForm{Container{name: "WINDOW窗口"}} win.AddChild(&Picture{Control{name: "LOGO图片"}}). AddChild(&Button{Control{name:"登录"}}). AddChild(&Button{Control{name:"注册"}}). AddChild(frame)
win.render(&StdPainter{format: "print %s(%s)\n"})}
复制代码


运行效果:


PS: 在 golang 中,对于类的继承并不完美,集成更多的像是在仅在结构体中包含另外一个结构体。

2.4 总结

组合模式适合用来处理有树状结构的设计。客户端可以一致地处理单个对象和组合对象,简化了客户端处理逻辑;更容易的在组合体内加入新的对象,满足“开闭原则”。


发布于: 2020 年 06 月 24 日阅读数: 103
用户头像

Season

关注

还未添加个人签名 2019.09.28 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第 3 周作业