软考中项学员:2016年3月9日作业
2016-03-17 08:30
267 查看
(注:代码在最底下的附件)
1.简单工厂
郭大神和盘哥在说好想买ipad,用代码实现一下
不用模式的设计
有何问题?
如果想买的iphone5时怎么办?
得找到所有new IpadProduct改成new IphoneProduct
而且改的是客户端的代码
应用模式的设计
无模式遇到的问题如何解决?
只要在SimpleFactory.getProdcut()换成IphoneProdcut即可
优点
创建对象收拢,扩展性加强了。
扩展时不需要修改客户端代码。
对象创建与使用解耦
缺点
多出一个工厂类
2.工厂方法
应用工厂方法模式的设计
优点
可以在不知道具体产品下实现编程
可以在不改变业务代码上很容易扩展出一个新的产品
缺点
多出几个具体工厂类
3.抽象工厂
考虑一下生产ipad和iphone的一个程序
工厂模式的设计有何问题?
工厂模式的设计有何问题?
客户端想只买一家公司的产品,客户端需要了解每种类型是出自哪一家公司?
港版ipad与iphone是出自同一家公司,美版ipad与iphone也是出自同一样公司,对于采购时
它只要报一下要什么哪个品牌的就可以买到同一个品牌的ipad和iphone
应用抽象工厂模式的设计
优点
缺点
深度思考
spring容器是最大的工厂
BeanFactory.getBean("xxx")
FileSystemXmlApplicationContext/ClassPathXmlApplicationContext
下面吐槽一下郭大神
考虑一下郭大神的家谱
...
郭大神的祖父
|
郭大神的父亲
|
郭大神
|
郭大神的儿子
...
郭大神的祖父创造了郭大神的父亲,郭大神的父新创造了郭大神,郭大神创造了郭大神的儿子
盘哥这边呢
...
盘哥的祖父
|
盘哥的父亲
|
盘哥
|
盘哥的儿子
...
用类来表示
如果我把郭明先生的祖父换成了姓郑(盘哥姓郑),则
当我换掉Grandfather时,奇迹出现了,整个家族的姓都变了。
从上面来看其实是工厂模式与工厂模式组合使用,经过组合后我们能写出具备极其扩展性的代码。
上面的原理是把工厂抽象成是一个产品(就是把工厂也当成是产品,那么生产这个产品的就是工厂的工厂。),于是就出现了"工厂的工厂的工厂"生产出"工厂的工厂","工厂的工厂"生产"工厂",最后工厂生成产品。这样就是级联使用工厂。
我们可以在任意一个环节替换实现,于是可以产生一个从大到小的扩展点。
考虑一下我们的建站平台框架的设计
站点有站点的接口, 同时还有站点资源接口(静态资源:js,css), 站点渲染接口, 站点数据接口。站点数据又可以分为站点数据读取接口, 和站点数据变更接口。
如果我设计下面这样的一个接口
经过上面这样设计之后, 如果我替换了SiteAPIFactory的实现, 我就可以操控整个站点的所有接口实现, 当我只替换SiteDataAPI时我能控制站点读取与写入数据的实现。也就是说从大到小的粒点扩展点我都支持了。做为平台的设计, 应用就可以根据需要自行替换实现。从而达到各种粒度的扩展。
很多模式都能组合起来使用,同时许多模式能与自身组合使用,像工厂,桥接等等
同时如果我写个SiteAPIUtil的获取SiteAPIFacotry,于是我就能提供所有接口了
再认真思考一下,你会发现SiteAPIUtil其实也是一个简单工厂,可以命名为SiteAPISimpleFactory
4.模板方法
考察一下郭大神与盘哥是如何上班的
不用模式的设计
不用模式有何问题?
他们两个上班过程基本上是一样的, 出现了重复的代码。
再考察一个人得同样要写很多重复的代码。
应用模式的设计
优点
没有重复的代码了,新增一个人时也同样减少一直重复的代码
如果在上班完加一个先吃个饭再回家,则只需要在抽象类里加上这行代码,无需改动所有Person
缺点
多出一个类,有时多出好几个方法
深度思考
模式方法模式其实就是一个抽象的过程,是最小抽象,位于抽象的最低层
与工厂方法的区别
总结:
简单工厂能把具体实现包装起来,让客户端真正达到面向接口编程
工厂方法可以在高层进行编码,让服务端的产品线真正达到面向接口编程
抽象工厂能聚合整个产品簇,让整个服务端的多个产品线真正达到面向接口编程
模板方法同样是在高层进行编码,也同样是面向接口编程。
但工厂方法及抽象工厂方法着重抽象的是产品,而模板方法着重抽象的是步骤。
而我们通常会两者一起结合起来使用。
思考上面那个模板模式,你会发现去上班和回到家代码很相似,
于是我们组合使用工厂模式又能去除重复代码。
在抽象类返回一个交通工具,上下班和回到家就可以在基类编程了。
代码如下:
这样,在AbstractPerson的子类只需要返回交通工具, 就可以少掉两个方法
1.简单工厂
郭大神和盘哥在说好想买ipad,用代码实现一下
不用模式的设计
public interface Product { String getDesc(); } public class IpadProduct implements Product { @Override public String getDesc() { return "Ipad2"; } } public class Client { public static void main(String[] args) { Product product = new IpadProduct(); System.out.println("郭大神说好想买" + product.getDesc() + ",但没钱!!!"); product = new IpadProduct(); System.out.println("盘哥说我好想买" + product.getDesc() + ",但没钱!!!"); } }
有何问题?
如果想买的iphone5时怎么办?
得找到所有new IpadProduct改成new IphoneProduct
而且改的是客户端的代码
应用模式的设计
public class IphoneProduct implements Product { @Override public String getDesc() { return "Iphone5"; } } public class SimpleFactory { public static Product getProdcut() { return new IpadProduct(); } } public class Client { public static void main(String[] args) { Product product = SimpleFactory.getProduct(); System.out.println("郭大神说好想买" + product.getDesc() + ",但没钱!!!"); product = SimpleFactory.getProduct(); System.out.println("盘哥说我好想买" + product.getDesc() + ",但没钱!!!"); } }
无模式遇到的问题如何解决?
只要在SimpleFactory.getProdcut()换成IphoneProdcut即可
优点
创建对象收拢,扩展性加强了。
扩展时不需要修改客户端代码。
对象创建与使用解耦
缺点
多出一个工厂类
2.工厂方法
应用工厂方法模式的设计
abstract public class Person { private String name; Person(String name){ this.name = name; } abstract Product getProduct(); public void say() { Product product = getProduct(); System.out.println(name + "说我好想买" + product.getDesc() + ",但没钱!!!"); } } public class GuoPerson extends Person { public GuoPerson(){ super("郭大神?); } @Override Product getProduct() { return new IpadProduct(); } } public class ShenPerson extends Person { public ShenPerson(){ super("盘哥"); } @Override Product getProduct() { return new IpadProduct(); } } public class ModeClient { public static void main(String[] args) { Person person = new GuoPerson(); person.say(); person = new ShenPerson(); person.say(); } }
优点
可以在不知道具体产品下实现编程
可以在不改变业务代码上很容易扩展出一个新的产品
缺点
多出几个具体工厂类
3.抽象工厂
考虑一下生产ipad和iphone的一个程序
工厂模式的设计有何问题?
public interface Ipad extends Product { } public class HongKongIpad implements Ipad { @Override public String getDesc() { return "香港版的Ipad"; } } public class USAIpad implements Ipad { @Override public String getDesc() { return "美国版的Iphone"; } } public interface Iphone extends Product { } public class HongKongIphone implements Iphone { @Override public String getDesc() { return "香港版的Iphone"; } } public class USAIphone implements Iphone { @Override public String getDesc() { return "美国版的Iphone"; } } public class SimpleFactory { public static Ipad createIpad(int type) { if (type == 1) { return new HongKongIpad(); } return new USAIpad(); } public static Iphone createIphone(int type) { if (type == 1) { return new HongKongIphone(); } return new USAIphone(); } } public class Client { public static void main(String[] args) { Ipad ipad = SimpleFactory.createIpad(1); Iphone iphone = SimpleFactory.createIphone(1); System.out.println("我采购的是:" + ipad.getDesc() + "和" + iphone.getDesc()); // ipad = SimpleFactory.createIpad(2); // iphone = SimpleFactory.createIphone(2); // System.out.println("我采购的是:" + ipad.getDesc() + "和" + iphone.getDesc()); } }
工厂模式的设计有何问题?
客户端想只买一家公司的产品,客户端需要了解每种类型是出自哪一家公司?
港版ipad与iphone是出自同一家公司,美版ipad与iphone也是出自同一样公司,对于采购时
它只要报一下要什么哪个品牌的就可以买到同一个品牌的ipad和iphone
应用抽象工厂模式的设计
public interface AppleFactory { Ipad createIpad(); Iphone createIphone(); } public class HongKongCompanyAppleFactory implements AppleFactory { @Override public Ipad createIpad() { return new HongKongIpad(); } @Override public Iphone createIphone() { return new HongKongIphone(); } } public class USACompanyAppleFactory implements AppleFactory { @Override public Ipad createIpad() { return new USAIpad(); } @Override public Iphone createIphone() { return new USAIphone(); } } public class ModeClient { public static void main(String[] args) { AppleFactory appleFactory = new HongKongCompanyAppleFactory(); Ipad ipad = appleFactory.createIpad(); Iphone iphone = appleFactory.createIphone(); System.out.println("我采购的是:" + ipad.getDesc() + "和" + iphone.getDesc()); // appleFactory = new USACompanyAppleFactory(); // ipad = appleFactory.createIpad(); // iphone = appleFactory.createIphone(); // System.out.println("我采购的是:" + ipad.getDesc() + "和" + iphone.getDesc()); } }
优点
缺点
深度思考
spring容器是最大的工厂
BeanFactory.getBean("xxx")
FileSystemXmlApplicationContext/ClassPathXmlApplicationContext
下面吐槽一下郭大神
考虑一下郭大神的家谱
...
郭大神的祖父
|
郭大神的父亲
|
郭大神
|
郭大神的儿子
...
郭大神的祖父创造了郭大神的父亲,郭大神的父新创造了郭大神,郭大神创造了郭大神的儿子
盘哥这边呢
...
盘哥的祖父
|
盘哥的父亲
|
盘哥
|
盘哥的儿子
...
用类来表示
interface Grandfather{ Father createFather(); } interface Father{ Self createSelf(); } interface Self { Son createSon(); }
如果我把郭明先生的祖父换成了姓郑(盘哥姓郑),则
当我换掉Grandfather时,奇迹出现了,整个家族的姓都变了。
从上面来看其实是工厂模式与工厂模式组合使用,经过组合后我们能写出具备极其扩展性的代码。
上面的原理是把工厂抽象成是一个产品(就是把工厂也当成是产品,那么生产这个产品的就是工厂的工厂。),于是就出现了"工厂的工厂的工厂"生产出"工厂的工厂","工厂的工厂"生产"工厂",最后工厂生成产品。这样就是级联使用工厂。
我们可以在任意一个环节替换实现,于是可以产生一个从大到小的扩展点。
考虑一下我们的建站平台框架的设计
站点有站点的接口, 同时还有站点资源接口(静态资源:js,css), 站点渲染接口, 站点数据接口。站点数据又可以分为站点数据读取接口, 和站点数据变更接口。
如果我设计下面这样的一个接口
interface SiteAPIFactory { getSiteAPI(); } interface SiteAPI{ getSiteResourceAPI(); getSiteDataAPI(); getRenderAPI(); } interface SiteDataAPI{ getSiteDataReadAPI(); getSiteDataDesignAPI(); } interface SiteDataReadAPI{ getSiteData(); } interface SiteDataDesignAPI{ updateSiteData(); deleteSiteData(); }
经过上面这样设计之后, 如果我替换了SiteAPIFactory的实现, 我就可以操控整个站点的所有接口实现, 当我只替换SiteDataAPI时我能控制站点读取与写入数据的实现。也就是说从大到小的粒点扩展点我都支持了。做为平台的设计, 应用就可以根据需要自行替换实现。从而达到各种粒度的扩展。
很多模式都能组合起来使用,同时许多模式能与自身组合使用,像工厂,桥接等等
同时如果我写个SiteAPIUtil的获取SiteAPIFacotry,于是我就能提供所有接口了
SiteAPIUtil{ SiteAPIFactory getSiteAPIFactory(){ DefaultSiteAPIFactory.instance }; SiteAPI getSiteAPI(){ getSiteAPIFactory().getSiteAPI(); }; SiteDataAPI getSiteDataAPI(){ getSiteAPI().getSiteDataAPI(); }; SiteDataDesignAPI getSiteDataDesignAPI(){ getSiteDataAPI().getSiteDesignAPI(); } ... }
再认真思考一下,你会发现SiteAPIUtil其实也是一个简单工厂,可以命名为SiteAPISimpleFactory
4.模板方法
考察一下郭大神与盘哥是如何上班的
不用模式的设计
public interface Person { String getName(); void summary(); } public class GuoPerson implements Person { @Override public void summary() { System.out.println(getName() + "起床"); System.out.println(getName() + "坐公交去上班"); System.out.println(getName() + "上班到9点时上了一次厕所"); System.out.println(getName() + "上班到10点时上了一次厕所"); System.out.println(getName() + "上班到11点时上了一次厕所"); System.out.println(getName() + "坐公交回到家"); System.out.println(getName() + "洗个澡睡觉了"); } @Override public String getName() { return "郭大神"; } } public class ShenPerson implements Person { @Override public void summary() { System.out.println(getName() + "起床"); System.out.println(getName() + "骑自行车去上班"); System.out.println(getName() + "上班到10点时上了一次厕所"); System.out.println(getName() + "骑自行车回到家"); System.out.println(getName() + "洗个澡睡觉了"); } @Override public String getName() { return "盘哥"; } } public class Client { public static void main(String[] args) { Person person = new GuoPerson(); person.summary(); person = new ShenPerson(); person.summary(); } }
不用模式有何问题?
他们两个上班过程基本上是一样的, 出现了重复的代码。
再考察一个人得同样要写很多重复的代码。
应用模式的设计
abstract public class AbstractPerson implements Person { public void summary() { System.out.println(getName() + "起床"); goToCompany(); work(); backToHome(); System.out.println(getName() + "洗个澡睡觉了"); } abstract public void goToCompany(); abstract public void work(); abstract public void backToHome(); } public class GuoPerson extends AbstractPerson { @Override public String getName() { return "郭大神"; } @Override public void goToCompany() { System.out.println(getName() + "坐公交去上班"); } @Override public void work() { System.out.println(getName() + "上班到9点时上了一次厕所"); System.out.println(getName() + "上班到10点时上了一次厕所"); System.out.println(getName() + "上班到11点时上了一次厕所"); } @Override public void backToHome() { System.out.println(getName() + "坐公交回到家"); } } public class ShenPerson extends AbstractPerson { @Override public String getName() { return "盘哥"; } @Override public void goToCompany() { System.out.println(getName() + "骑自行车去上班"); } @Override public void work() { System.out.println(getName() + "上班到10点时上了一次厕所"); } @Override public void backToHome() { System.out.println(getName() + "骑自行车回到家"); } } public class ModelClient { public static void main(String[] args) { Person person = new GuoPerson(); person.summary(); person = new ShenPerson(); person.summary(); } }
优点
没有重复的代码了,新增一个人时也同样减少一直重复的代码
如果在上班完加一个先吃个饭再回家,则只需要在抽象类里加上这行代码,无需改动所有Person
缺点
多出一个类,有时多出好几个方法
深度思考
模式方法模式其实就是一个抽象的过程,是最小抽象,位于抽象的最低层
与工厂方法的区别
总结:
简单工厂能把具体实现包装起来,让客户端真正达到面向接口编程
工厂方法可以在高层进行编码,让服务端的产品线真正达到面向接口编程
抽象工厂能聚合整个产品簇,让整个服务端的多个产品线真正达到面向接口编程
模板方法同样是在高层进行编码,也同样是面向接口编程。
但工厂方法及抽象工厂方法着重抽象的是产品,而模板方法着重抽象的是步骤。
而我们通常会两者一起结合起来使用。
思考上面那个模板模式,你会发现去上班和回到家代码很相似,
于是我们组合使用工厂模式又能去除重复代码。
在抽象类返回一个交通工具,上下班和回到家就可以在基类编程了。
代码如下:
public interface Vehicle { String by(); } public class Bus implements Vehicle { @Override public String by() { return "坐公交车"; } } public class Bike implements Vehicle { @Override public String by() { return "骑自行车"; } } abstract public class AbstractPerson implements Person { public void summary() { Vehicle vehicle = getVehicle(); System.out.println(getName() + "起床"); System.out.println(getName() + vehicle.by() + "去上班"); work(); System.out.println(getName() + vehicle.by() + "回到家"); System.out.println(getName() + "洗个澡睡觉了"); } abstract public Vehicle getVehicle(); abstract public void work(); } public class GuoPerson extends AbstractPerson { @Override public String getName() { return "郭大神"; } @Override public void work() { System.out.println(getName() + "上班到9点时上了一次厕所"); System.out.println(getName() + "上班到10点时上了一次厕所"); System.out.println(getName() + "上班到11点时上了一次厕所"); } @Override public Vehicle getVehicle() { return new Bus(); } } public class ShenPerson extends AbstractPerson { @Override public String getName() { return "盘哥"; } @Override public void work() { System.out.println(getName() + "上班到10点时上了一次厕所"); } @Override public Vehicle getVehicle() { return new Bike(); } }
这样,在AbstractPerson的子类只需要返回交通工具, 就可以少掉两个方法
相关文章推荐
- 打印零形2
- 第四周项目1 之求最大公约数和最小公倍数
- 编程小练习9
- 软考中项学员:2016年3月7日作业
- HTTP请求响应方式总结
- Android:Android Support Design之TabLayout使用详解
- 第三周项目二本月有几天?
- MVC,EF 小小封装,mvcef封装
- 黑马day16 jquery入门
- PHPExcel的使用与手册说明
- 2016.3.17
- 第3周项目4-(1)百钱买百鸡问题
- man 2 accept
- Android Studio使用指南(2)
- 打印菱形
- Spring核心之BeanFactory 一张图看懂getBean全过程.
- ios的动画
- HDU 4507 吉哥系列故事——恨7不成妻
- express 4.x与angular最简单的通信
- python中的TCP编程学习