首页IT科技抽象工厂模式结构图(设计模式—抽象工厂模式)

抽象工厂模式结构图(设计模式—抽象工厂模式)

时间2025-06-20 15:30:19分类IT科技浏览3867
导读:简述 类型:创建型...

简述

类型:创建型

目的:实现对客户端中对象族的平替             。

对象族 具有共同主题的一组对象的集合                    。比如             ,华为的手机                    ,笔记本       ,平板可以统称为华为族       。

我们借以下案例来说说如何使用抽象工厂模式平替对象族             。

优化案例

最初版

// 上传模块的接口 public interface Uploader { void upload(String fileName); } // 下载模块的接口 public interface Downloader { void download(String fileName); } // Linux环境下的上传实现 public class LinuxUploader implements Uploader { public void upload(String fileName) { System.out.printf("[Linux]正在上传%s...", fileName); } } // Linux环境下的下载实现 public class LinuxDownloader implements Downloader { public void download(String fileName) { System.out.printf("[Linux]正在下载%s...", fileName); } } // Unix环境下的上传实现 public class UnixUploader implements Uploader { public void upload(String fileName) { System.out.printf("[Unix]正在上传%s...", fileName); } } // Unix环境下的下载实现 public class UnixDownloader implements Downloader { public void download(String fileName) { System.out.printf("[Unix]正在下载%s...", fileName); } }

客户端调用如下                   。

public class Client { public static void main(String[] args) { Uploader uploader = new LinuxUploader(); Downloader downloader = new LinuxDownloader(); } }

传统是new创建对象的方式有着硬编码的问题       。当我们需要把所有LinuxXXX对象改为UnixXXX对象时      ,就必须在项目中检索所有的LinuxXXX修改为UnixXXX       。这无疑增加了大量的无意义的工作                   。

修改版v1(简单工厂)

增加一个工厂类                    ,其他不变             。

// 简单工厂 public class Factory { static Uploader uploader(String target) { if ("LinuxUploader".equals(target)) { return new LinuxUploader(); } else if ("UnixUploader".equals(target)) { return new UnixUploader(); } throw new Exception("输入的参数错误"); } static Downloader downloader(String target) { if ("LinuxDownloader".equals(target)) { return new LinuxDownloader(); } else if ("UnixDownloader".equals(target)) { return new UnixDownloader(); } throw new Exception("输入的参数错误"); } }

修改后             ,客户端的代码调用       。

public class Client { public static void main(String[] args) { Uploader up1 = Factory.instance("LinuxUploader"); Downloader down1 = Factory.instance("LinuxDownloader"); Uploader up2 = Factory.instance("UnixUploader"); Downloader down2 = Factory.instance("UnixDownloader"); } }

在一定程度上解决了客户端硬编码问题                    。并且当我们需要把所有LinuxUploader对象改为UnixUploader对象时      ,只需要在Factory中将new LinuxUploader() → new UnixUploader()即可             。这无疑节省了很多的时间                    ,也无需为硬编码带来的大量改修而苦恼。

但是目前这个优化方案依然有至少两个问题             ,一是Factory.uploader方法中耦合了所有的Uploader实现类,这可能有碍于未来的项目维护                    ,二是new LinuxUploader() → new UnixUploader()这种修改方式会导致代码目的不明确                    ,既然不论是LinuxUploader还是UnixUploader都直接生成UnixUploader对象,就没有必要定义LinuxUploader了呀                    。实际上是因为客户端代码中还有使用OSFactory.instance("LinuxUploader")来创建的对象             ,为了不修改客户端代码                    ,强行做如上修改                    。

修改版v2(抽象工厂)

将原本的工厂类抽象化       ,并定义一系列不同的实现类             ,其余不变。

// 抽象的工厂接口 public interface Factory { Uploader uploader(); Downloader downloader(); } // Linux环境下的工厂实现 public class LinuxFactory { public Uploader uploader() { return new LinuxUploader(); } public Downloader downloader() { return new LinuxDownloader(); } } // Uinx环境下的工厂实现 public class UnixFactory { public Uploader uploader() { return new UnixUploader(); } public Downloader downloader() { return new UnixDownloader(); } }

修改后                    ,客户端的代码调用             。

public class Client { private static Factory factory = new LinuxFactory(); public static void main(String[] args) { Uploader uploader = factory.uploader(); Downloader downloader = factory.downloader(); } }

将原本Factory类中臃肿的逻辑分散到各个子类中       ,提高了系统的可维护性      ,不用再每次都修改Factory类了                    。

那么                    ,问题来了             ,这样的结构对于我们的项目有什么帮助吗?有      ,而且很大                    ,在客户端定义了一个静态的属性factory             ,当接下来客户换了系统从Linux换到了Unix,那我们也需要更换对应的上传下载的类                    ,这时我们只要修改factory引用的具体工厂类的对象就可以了                    ,很方便       。实际上还可以更加方便的实现对象族的平替             。而为了实现这个需求,我们需要结合Java反射这项技术                   。请看下面的代码       。

修改版v3(抽象工厂+反射)

只修改客户端的调用方式             ,其他位置不做修改       。

public class Client { private static Factory factory; // 通过Java的反射机制创建上述factory对象 static { // 读取prop配置文件 Properties prop = new Properties(); FileReader fileReader = new FileReader("src/resource/props/config.prop"); prop.load(fileReader); fileReader.close(); factory = (Factory) Class.forName(prop.getProperty("FACTORY")) .getDeclaredConstructor().newInstance(); } public static void main(String[] args) { Uploader uploader = factory.uploader(); Downloader downloader = factory.downloader(); } }

增加一个properties文件文件                    ,定义如下                   。

#当前使用的工厂类 FACTORY=design.abstractfactory.LinuxFactory

当需要将系统中的Linux系列的对象转化为Unix系列时       ,只需要更改上述配置文件即可             ,具体如下             。

#当前使用的工厂类 FACTORY=design.abstractfactory.UnixFactory

总之就是非常方便       。

总结

优点

轻松做到对象族的平替                    。

缺点

类数量倍增                    ,系统复杂度增加             。

应用场景

根据需求       ,需要全面替换系统中的某个对象族时。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
买卖股票的最佳时机 java(每日算法题之买卖股票的最好时机(一))