设计模式(建造者与模板方法)
这篇文章用来总结一下工作一些设计思想。
以前记得我们的CTO跟我们说过,“Java是一门面向对象的语言,不要把他写成了C语言(面向过程)”。意思就是说没有封装不懂得使用OOD,OOP在实际生产过程中。
封装是为了方便扩展。说白了Java的设计模式其目的就是为了方便扩展。
我们公司产品 需要打印 两种类型的小票,一种是纸款是 58 的打印小票,一种是 纸款 80 的打印小票。打印内容类似,打印出来的样式不一样。
打印方式 采用的是位图 (Bitmap)打印, 将小票生成 一个bitmap,然后发送到打印机打印。
这是一张58小票:
主要有三到四部分组成
1. 头 Header (商家信息 logo ,服务员信息,下单时间等)
2. 中间 Mid (点菜的主要信息)
3. 底部 Bottom (一价格信息)
4. 结束 end (商家地址部分)
小票主要是由这几部分组成的,不管是 80 或者 58 小票。 区别在于 样式不一样。
如果根据 58 或者 80 类型去生成小票
if(58){
//生成 58 小票
}else if(80){
//生成 80 小票
}
这样的写法是C语言的写法。Java 是一门面向对象的语言我们就要用面向对象的思想进行思考。
(1)抽象
1.提取公共属性 , 每种小票都是 有这四部分组成的。我的思路就
头,中,尾,结束 这四部分,各自生成自己的Bitmap 然后组成 一个新的bitmap 。
这样我们就可以将 生成 头,中,尾,结束 抽象出来了。
而这几部分 都有一些共同的特性
设置数据, 生成视图等 ,所以我们 抽象了一个接口
FrontTicketViewCreater :
/**
* @Author linyong
* @Date 2016/8/23
* @Time 10:39
*/
public interface FrontTicketViewCreater {
/**
* 设置小票数据
*
* @param orders
*/
void setData(Orders orders);
/**
* 加载小票配置
*
* @param frontTicketConfigs
*/
void setTicketConfigs(FrontTicketConfigs frontTicketConfigs);
/**
* 设置上下文
*
* @param context
*/
void setContext(Context context);
/**
* 生成view
*
* @return
*/
View createView();
}
FrontTicketHeaderCreater,FrontTicketMiddleCreater,FrontTicketEndCreater,FrontTicketBottomCreater 繼承 FrontTicketViewCreater 。
有同学会问 FrontTicketHeaderCreater … 等为什么不抽象成接口,
因为我们需要在里面初始化一下公共的属性。所以不适用接口。
那我们要生成头部 ,我们就这样:
//58 头部生成器繼承了 刚刚的头部 生成器FrontTicketHeaderCreater
public class FiftyFrontTicketHeaderCreater extends FrontTicketHeaderCreater{
//....
}
//80 头部生成器 繼承了 刚刚的头部 生成器FrontTicketHeaderCreater
public class EightyFrontTicketHeaderCreater extends FrontTicketHeaderCreater{
//....
}
其他部分类似。
现在我们 缺少一个 管理 这些生成器的 一个类。也就是说欠缺一个建造者。
FrontTicketBuilder 用来管理和创建小票的生成。
/**
* @Author linyong
* @Date 2016/8/20
* @Time 17:15
* 前台小票 生成器
*/
public class FrontTicketBuilder {
/**
*
*/
private FrontTicketHeaderCreater ticketHeaderCreater;
private FrontTicketMiddleCreater ticketMiddleCreater;
private FrontTicketBottomCreater ticketBottomCreater;
private FrontTicketEndCreater ticketEndCreater;
/**
*
*/
private Orders orders;
private Context context;
private View view;
private FrontTicketConfigs ticketConfigs;
private FrontTicketCreateTypeEnum createTypeEnum = FrontTicketCreateTypeEnum.TYPE_PRINT;
public FrontTicketBuilder() {
}
/**
* 创建头部
*
* @param ticketHeaderCreater
* @return
*/
public FrontTicketBuilder createTicketHeader(FrontTicketHeaderCreater ticketHeaderCreater) {
this.ticketHeaderCreater = ticketHeaderCreater;
this.ticketHeaderCreater.setContext(context);
this.ticketHeaderCreater.setData(orders);
this.ticketHeaderCreater.setTicketConfigs(ticketConfigs);
this.ticketHeaderCreater.setCreateType(createTypeEnum);
return this;
}
/**
* 创建 中间部分
* (菜品内容)
*
* @param ticketMiddleCreater
* @return
*/
public FrontTicketBuilder createTicketMiddle(FrontTicketMiddleCreater ticketMiddleCreater) {
this.ticketMiddleCreater = ticketMiddleCreater;
this.ticketMiddleCreater.setContext(context);
this.ticketMiddleCreater.setData(orders);
this.ticketMiddleCreater.setTicketConfigs(ticketConfigs);
this.ticketMiddleCreater.setCreateType(createTypeEnum);
return this;
}
/**
* 创建底部 (支付信息)
*
* @param ticketBottomCreater
* @return
*/
public FrontTicketBuilder createTicketBottom(FrontTicketBottomCreater ticketBottomCreater) {
this.ticketBottomCreater = ticketBottomCreater;
this.ticketBottomCreater.setTicketConfigs(ticketConfigs);
this.ticketBottomCreater.setData(orders);
this.ticketBottomCreater.setContext(context);
this.ticketBottomCreater.setCreateType(createTypeEnum);
return this;
}
/**
* 创建最底部 (商家信息)
*
* @param ticketEndCreater
* @return
*/
public FrontTicketBuilder createTicketEnd(FrontTicketEndCreater ticketEndCreater) {
this.ticketEndCreater = ticketEndCreater;
this.ticketEndCreater.setContext(context);
this.ticketEndCreater.setData(orders);
this.ticketEndCreater.setTicketConfigs(ticketConfigs);
this.ticketEndCreater.setCreateType(createTypeEnum);
return this;
}
/**
* 设置订单数据
*
* @param orders
* @return
*/
public FrontTicketBuilder setData(Orders orders) {
this.orders = orders;
return this;
}
/**
* 设置 上下文
*
* @param context
* @return
*/
public FrontTicketBuilder setContext(Context context) {
this.context = context;
return this;
}
/**
* 加载配置
*
* @param ticketConfigs
* @return
*/
public FrontTicketBuilder setTicketConfigs(FrontTicketConfigs ticketConfigs) {
this.ticketConfigs = ticketConfigs;
return this;
}
/**
* 生成 试图
*
* @return
*/
public View build() {
LinearLayout content_layout = getPaper();
if (null != ticketHeaderCreater) {
View headerView = ticketHeaderCreater.createView();
if (null != headerView)
content_layout.addView(headerView);
}
if (null != ticketMiddleCreater) {
View middleView = ticketMiddleCreater.createView();
if (null != middleView)
content_layout.addView(middleView);
}
if (null != ticketBottomCreater) {
View bottomView = ticketBottomCreater.createView();
if (null != bottomView)
content_layout.addView(bottomView);
}
if (null != ticketEndCreater) {
View endView = ticketEndCreater.createView();
if (null != endView)
content_layout.addView(endView);
}
return view;
}
/**
* 根据配置获取纸张大小
*
* @return
*/
private LinearLayout getPaper() {
LinearLayout content_layout;
if (ticketConfigs.getPaperSpec().equals(FrontTicketSpecEnum.Ticket_Paper58.getDesc())) {
//设置58的打印纸
view = LayoutInflater.from(context).inflate(R.layout.front_ticket_template_58_layout, null);
if (createTypeEnum.getType() == 1) {
}
} else if (ticketConfigs.getPaperSpec().equals(FrontTicketSpecEnum.Ticket_Paper80.getDesc())) {
// 设置80的打印纸
view = LayoutInflater.from(context).inflate(R.layout.front_ticket_template_80_layout, null);
}
content_layout = (LinearLayout) view.findViewById(R.id.content_layout);
return content_layout;
}
}
这就是小票建造者,生成小票代码(这里是 58的):
View v = new FrontTicketBuilder().setContext(getContext()).setData(orders)
.setTicketConfigs(tmpFrontTicketConfigs)
.createTicketHeader(new FiftyFrontTicketHeaderCreater())
.createTicketMiddle(new FiftyFrontTicketMiddleCreater())
.createTicketBottom(new FiftyFrontTicketBottomCreater())
.createTicketEnd(new FiftyFrontTicketEndCreater())
.build();
这样就可以生成打印 视图了 ,哈哈 是不是很强大,也很容易扩展。
。
以后如果 还有其他类型的小票扩展就行了。