您的位置:首页 > 其它

软考中项学员:2016年3月9日作业

2016-03-17 08:30 267 查看
(注:代码在最底下的附件)
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的子类只需要返回交通工具, 就可以少掉两个方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: