架构师训练营第 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 日 阅读数: 75
用户头像

Season

关注

还未添加个人签名 2019.09.28 加入

还未添加个人简介

评论

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