上一次总结了创建型模式
这次来总结一下结构型模式 共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
结构型模式
适配器模式
适配器模式分为三种:
- 类的适配器模式
- 对象的适配器模式
- 接口的适配器模式
/**
* 适配器模式
*
* 适配器模式分为三种:
1. 类的适配器模式
2. 对象的适配器模式
3. 接口的适配器模式
*
*/
public class Two_AdapterPatterns {
public static void main(String[] args) {
//类适配器
Target target=new AdapterClass();
target.method1();
target.method2();
//对象适配器
Source source=new Source();
Target target2=new Wrapper(source);
target2.method1();
target2.method2();
//接口适配器
Target target3=new AdapterInplements();
target3.method1();
target3.method2();
}
}
/**
* 核心思想就是:有一个Source类,拥有一个方法,待适配,目标接口时
* Targetable,通过Adapter类,将Source的功能扩展到Targetable里,
* @author chris
*
*/
class AdapterClass extends Source implements Target{
@Override
public void method2() {
// TODO Auto-generated method stub
System.out.println("实现接口中的方法");
}
}
/**
* 对象适配器
* 基本思路和类的适配器模式相同,只是将Adapter类作修改,
* 这次不继承Source类,而是持有Source类的实例,以达到解决兼容性
* 的问题。
* @author chris
*
*/
class Wrapper implements Target{
private Source source;
public Wrapper(Source source){
super();
this.source=source;
}
@Override
public void method1() {
// TODO Auto-generated method stub
System.out.println("method1");
}
@Override
public void method2() {
// TODO Auto-generated method stub
source.method1();
}
}
/**
* 接口适配器
* @author chris
*
*/
class AdapterInplements extends AllMethod{
@Override
public void method1() {
// TODO Auto-generated method stub
super.method1();
System.out.println("其中一个");
}
}
abstract class AllMethod implements Target{
@Override
public void method1() {
// TODO Auto-generated method stub
}
@Override
public void method2() {
// TODO Auto-generated method stub
}
}
class Source{
public void method1(){
System.out.println("接口中相同的方法");
}
}
interface Target{
public void method1();
public void method2();
}
桥接模式
将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了。
桥接模式就是把事物和其具体实现分开,使他们可以各自独立的变化。
/**
* 桥接模式(Bridge)
* @author chris
*将抽象化与实现化解耦,使得二者可以独立变化,像我们常用的JDBC桥DriverManager一样,
*JDBC进行连接数据库的时候,在各个数据库之间进行切换,基本不需要动太多的代码,甚至丝毫不用动,
*原因就是JDBC提供统一接口,每个数据库提供各自的实现,用一个叫做数据库驱动的程序来桥接就行了
*/
public class Two_BridgePatterns {
public static void main(String[] args) {
DriverManager dm=new DriverManager();
MySql mysql=new MySql();
dm.setDriver(mysql);
dm.method();
Oracle oracle=new Oracle();
dm.setDriver(oracle);
dm.method();
}
}
/**
* Driver桥
* @author chris
*
*/
class DriverManager implements Driver{
Driver driver ;
@Override
public void method() {
driver.method();
}
public void setDriver(Driver driver){
this.driver=driver;
}
public Driver getDriver(){
return driver;
}
}
class MySql implements Driver{
@Override
public void method() {
// TODO Auto-generated method stub
System.out.println("mysql instance");
}
}
class Oracle implements Driver{
@Override
public void method() {
// TODO Auto-generated method stub
System.out.println("oracle instance");
}
}
interface Driver{
public void method();
}
抽象工厂模式
创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
/**
* 抽象工厂模式(Abstract Factory) 创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。
*
*/
public class One_AbstractFactoryPatterns {
public static void main(String[] args) {
Provider provider = new SendSmsFactory();
AbstractSender sender = provider.getSender();
sender.Sender();
}
}
class SendSmsFactory implements Provider {
@Override
public AbstractSender getSender() {
// TODO Auto-generated method stub
return new AbstractMailSender();
}
}
class SendMailFactory implements Provider {
@Override
public AbstractSender getSender() {
// TODO Auto-generated method stub
return new AbstractMailSender();
}
}
/**
* 工厂类共同实现rpovider接口
*
* @author chris
*
*/
interface Provider {
public AbstractSender getSender();
}
class AbstractMailSender implements AbstractSender {
@Override
public void Sender() {
// TODO Auto-generated method stub
System.out.println("MailSender");
}
}
class AbstractSmsSender implements AbstractSender {
@Override
public void Sender() {
// TODO Auto-generated method stub
System.out.println("SmsSender");
}
}
interface AbstractSender {
public void Sender();
}
组合模式
组合模式有时又叫部分-整体模式在处理类似树形结构的问题时比较方便
/**
* 组合模式(Composite)
* @author chris
*将多个对象组合在一起进行操作,常用于表示树形结构中,
*链表
*例如二叉树,数等。
*/
public class Two_CompositePatterns {
TreeNode root=null;
static Enumeration<TreeNode> children=null;
public Two_CompositePatterns(String name){
root=new TreeNode(name);
}
public static void main(String[] args) {
Two_CompositePatterns tree=new Two_CompositePatterns("a");
TreeNode nodeB=new TreeNode("B");
TreeNode nodec=new TreeNode("C");
TreeNode noded=new TreeNode("D");
TreeNode nodee=new TreeNode("E");
nodeB.add(nodec);
nodec.add(noded);
noded.add(nodee);
tree.root.add(nodeB);//添加到根节点
children=tree.root.getChilden();
TreeNode treeNode ;
while(children.hasMoreElements()){
treeNode=children.nextElement();
System.out.println(" "+treeNode.getName());
children=treeNode.getChilden();
}
System.out.println("成功");
}
}
class TreeNode{
private String name;
private TreeNode parent;
private Vector<TreeNode> children=new Vector<TreeNode>();
public TreeNode(String name){
this.name=name;
}
public void setName(){
this.name=name;
}
public String getName(){
return name;
}
public void setParent(TreeNode parent){
this.parent=parent;
}
public TreeNode getParent(){
return parent;
}
public void add(TreeNode node){
children.add(node);
}
public void remove(TreeNode node){
children.remove(node);
}
public Enumeration<TreeNode> getChilden(){
return children.elements();
}
}
装饰模式
装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和 被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
* 1、需要扩展一个类的功能。
* 2、动态的为一个对象增加功能,而且还能动态撤销。(继承不能做到这一点,继承的功能是静态的,不能动态增删。)
* 缺点:产生过多相似的对象,不易排错!
public class Two_DecoratorPatterns {
public static void main(String[] args) {
SourceOne one=new SourceOne();
SourceTwo two=new SourceTwo(one);
two.method();
}
}
class SourceTwo implements SourceAble{
private SourceAble source;
public SourceTwo(SourceAble one){
super();
this.source=one;
}
@Override
public void method() {
System.out.println("sourceTwo执行的方法");
source.method();
System.out.println("添加方法后执行的");
}
}
class SourceOne implements SourceAble{
@Override
public void method() {
System.out.println("souceOne要添加的方法");
}
}
interface SourceAble {
public void method();
}
外观模式(Facade)
外观模式是为了解决类与类之家的依赖关系的,像spring一样,可以将类和类之间的关系配置到配置文件中 ,降低了类类之间的耦合度
public class Two_FacadePatterns {
public static void main(String[] args) {
Cumpter cumpter=new Cumpter();
cumpter.start();
cumpter.shutdown();
}
}
class Cumpter{
Cpu cpu=null;
Memory memory=null;
Disk disk=null;
public Cumpter(){
cpu=new Cpu();
memory=new Memory();
disk=new Disk();
}
public void start(){
System.out.println("开机");
cpu.start();
memory.start();
disk.start();
}
public void shutdown (){
System.out.println("关机");
cpu.shutdown();
memory.shutdown();
memory.shutdown();
}
}
class Cpu{
public void start(){
System.out.println("Cpu start");
}
public void shutdown(){
System.out.println("Cpu shutdown");
}
}
class Memory{
public void start(){
System.out.println("Memory start");
}
public void shutdown(){
System.out.println("Memory shutdown");
}
}class Disk{
public void start(){
System.out.println("Disk start");
}
public void shutdown(){
System.out.println("Disk shutdown");
}
}
享元模式
享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多的时候可以减少内存的开销,通常与工厂模式一起使用
FlyWeightFactory负责创建和管理享元单元,当一个客户端请求时,工厂需要检查当前对象池中是否有符合条件的对象,如果有,就返回已经存在的对象,如果没有,则创建一个新对象,FlyWeight是超类。
/**
* 享元模式(Flyweight)
* @author chris
*享元模式的主要目的是实现对象的共享,即共享池,当系统中对象多
*的时候可以减少内存的开销,通常与工厂模式一起使用。
*/
public class Two_FlyweightPatterns {
private Vector<Connection> pool;
/**公有属性*/
private String url = "jdbc:mysql://localhost:3306/test";
private String username = "root";
private String password = "root";
private String driverClassName = "com.mysql.jdbc.Driver";
private int poolSize = 100;
private static Two_FlyweightPatterns instance = null;
Connection conn = null;
/**构造方法,做一些初始化工作*/
private Two_FlyweightPatterns() throws SQLException {
pool = new Vector<Connection>(poolSize);
for (int i = 0; i < poolSize; i++) {
try {
Class.forName(driverClassName);
// conn = DriverManager.getConnection(url, username, password);
pool.add(conn);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
/** 返回连接到连接池 */
public synchronized void release() {
pool.add(conn);
}
/**返回连接池中的一个数据库连接 */
public synchronized Connection getConnection() {
if (pool.size() > 0) {
Connection conn = pool.get(0);
pool.remove(conn);
return conn;
} else {
return null;
}
}
}
代理模式
代理模式就是多一个代理类出来,替原对象进行一些操作,
为其他对象提供一种代理以控制对这个对象的访问。
/**
* 代理模式 Proxy
*
*代理模式的应用场景:
如果已有的方法在使用的时候需要对原有的方法进行改进,此时有两种办法:
1、修改原有的方法来适应。这样违反了“对扩展开放,对修改关闭”的原则。
2、就是采用一个代理类调用原有的方法,且对产生的结果进行控制。这种方法就是代理模式。
使用代理模式,可以将功能划分的更加清晰,有助于后期维护!
*/
public class Two_ProxyPatterns {
public static void main(String[] args) {
ProxyTwo pr=new ProxyTwo();
pr.method();
}
}
class ProxyTwo implements ProxyInterface{
ProxyInterface face;
public ProxyTwo(){
super();
face=new ProxyOne();
}
@Override
public void method() {
// TODO Auto-generated method stub
before();
face.method();
after();
}
public void before(){
System.out.println("添加代理中特有的方法");
}
public void after(){
System.out.println("添加代理中之后的方法");
}
}
class ProxyOne implements ProxyInterface{
@Override
public void method() {
// TODO Auto-generated method stub
System.out.println("proxyOne");
}
}
interface ProxyInterface{
public void method();
}